This commit is contained in:
Ryan VanderMeulen 2013-05-22 10:01:52 -04:00
Родитель 5018318374 f906b641d5
Коммит a572f71b43
20 изменённых файлов: 573 добавлений и 60 удалений

Просмотреть файл

@ -988,7 +988,7 @@ respond_with_ok:
}
void
BluetoothHfpManager::Connect(const nsAString& aDevicePath,
BluetoothHfpManager::Connect(const nsAString& aDeviceAddress,
const bool aIsHandsfree,
BluetoothReplyRunnable* aRunnable)
{
@ -997,6 +997,9 @@ BluetoothHfpManager::Connect(const nsAString& aDevicePath,
NS_ENSURE_FALSE_VOID(gInShutdown);
NS_ENSURE_FALSE_VOID(mSocket);
mNeedsUpdatingSdpRecords = true;
mIsHandsfree = aIsHandsfree;
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
@ -1007,10 +1010,9 @@ BluetoothHfpManager::Connect(const nsAString& aDevicePath,
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid);
}
if (NS_FAILED(bs->GetServiceChannel(aDevicePath, uuid, this))) {
BluetoothValue v;
DispatchBluetoothReply(aRunnable, v,
NS_LITERAL_STRING("GetServiceChannelError"));
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
return;
}
@ -1487,30 +1489,69 @@ BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
Reset();
}
void
BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
nsString uuid;
if (mIsHandsfree) {
BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
} else {
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid);
}
// Since we have updated SDP records of the target device, we should
// try to get the channel of target service again.
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
}
}
void
BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
BluetoothValue v;
if (aChannel < 0) {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING("DeviceChannelRetrievalError"));
mSocket = nullptr;
Listen();
if (mNeedsUpdatingSdpRecords) {
mNeedsUpdatingSdpRecords = false;
bs->UpdateSdpRecords(aDeviceAddress, this);
} else {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
}
return;
}
if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING("SocketConnectionError"));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
return;
}
}

Просмотреть файл

@ -67,8 +67,9 @@ public:
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
void Connect(const nsAString& aDeviceObjectPath,
void Connect(const nsAString& aDeviceAddress,
const bool aIsHandsfree,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
@ -131,6 +132,8 @@ private:
int mNetworkSelectionMode;
bool mReceiveVgsFlag;
bool mBLDNProcessed;
bool mIsHandsfree;
bool mNeedsUpdatingSdpRecords;
nsString mDeviceAddress;
nsString mMsisdn;
nsString mOperatorName;

Просмотреть файл

@ -251,7 +251,7 @@ BluetoothOppManager::Get()
}
void
BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -261,13 +261,14 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
mNeedsUpdatingSdpRecords = true;
nsString uuid;
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceObjectPath, uuid, this))) {
BluetoothValue v;
DispatchBluetoothReply(aRunnable, v,
NS_LITERAL_STRING("GetServiceChannelError"));
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
return;
}
@ -1371,7 +1372,7 @@ BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket)
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
}
mRunnable.forget();
mRunnable = nullptr;
}
// Cache device address since we can't get socket address when a remote
@ -1383,10 +1384,9 @@ void
BluetoothOppManager::OnConnectError(BluetoothSocket* aSocket)
{
if (mRunnable) {
BluetoothValue v;
DispatchBluetoothReply(mRunnable, v,
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING("OnConnectError:no runnable"));
mRunnable.forget();
mRunnable = nullptr;
}
mSocket = nullptr;
@ -1434,24 +1434,55 @@ BluetoothOppManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
int aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothValue v;
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
if (aChannel < 0) {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING("DeviceChannelRetrievalError"));
mSocket = nullptr;
Listen();
if (mNeedsUpdatingSdpRecords) {
mNeedsUpdatingSdpRecords = false;
bs->UpdateSdpRecords(aDeviceAddress, this);
} else {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
}
return;
}
if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) {
DispatchBluetoothReply(mRunnable, v,
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING("SocketConnectionError"));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
}
}
void
BluetoothOppManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
nsString uuid;
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
return;
}
}

Просмотреть файл

@ -52,7 +52,7 @@ public:
* either call Disconnect() to close RFCOMM connection or start another
* file-sending thread via calling SendFile() again.
*/
void Connect(const nsAString& aDeviceObjectPath,
void Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
bool Listen();
@ -88,6 +88,7 @@ public:
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
private:
BluetoothOppManager();
@ -138,6 +139,12 @@ private:
int mReceivedDataBufferOffset;
int mUpdateProgressCounter;
/**
* When it is true and the target service on target device couldn't be found,
* refreshing SDP records is necessary.
*/
bool mNeedsUpdatingSdpRecords;
/**
* Set when StopSendingFile() is called.
*/

Просмотреть файл

@ -7,6 +7,8 @@
#ifndef mozilla_dom_bluetooth_bluetoothprofilemanagerbase_h__
#define mozilla_dom_bluetooth_bluetoothprofilemanagerbase_h__
#define ERR_SERVICE_CHANNEL_NOT_FOUND "DeviceChannelRetrievalError"
#include "BluetoothCommon.h"
BEGIN_BLUETOOTH_NAMESPACE
@ -17,6 +19,8 @@ public:
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) = 0;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) = 0;
};
END_BLUETOOTH_NAMESPACE

Просмотреть файл

@ -222,10 +222,14 @@ public:
* @return NS_OK if the task begins, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
GetServiceChannel(const nsAString& aObjectPath,
GetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
BluetoothProfileManagerBase* aManager) = 0;
virtual bool
UpdateSdpRecords(const nsAString& aDeviceAddress,
BluetoothProfileManagerBase* aManager) = 0;
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) = 0;

Просмотреть файл

@ -41,6 +41,12 @@ TelephonyListener::CallStateChanged(uint32_t aCallIndex,
return NS_OK;
}
NS_IMETHODIMP
TelephonyListener::EnumerateCallStateComplete()
{
return NS_OK;
}
NS_IMETHODIMP
TelephonyListener::EnumerateCallState(uint32_t aCallIndex,
uint16_t aCallState,

Просмотреть файл

@ -207,7 +207,7 @@ BluetoothServiceChildProcess::GetScoSocket(
}
nsresult
BluetoothServiceChildProcess::GetServiceChannel(const nsAString& aObjectPath,
BluetoothServiceChildProcess::GetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
BluetoothProfileManagerBase* aManager)
{
@ -215,6 +215,14 @@ BluetoothServiceChildProcess::GetServiceChannel(const nsAString& aObjectPath,
return NS_ERROR_FAILURE;
}
bool
BluetoothServiceChildProcess::UpdateSdpRecords(const nsAString& aDeviceAddress,
BluetoothProfileManagerBase* aManager)
{
MOZ_NOT_REACHED("This should never be called!");
return NS_ERROR_FAILURE;
}
bool
BluetoothServiceChildProcess::SetPinCodeInternal(
const nsAString& aDeviceAddress,

Просмотреть файл

@ -87,10 +87,14 @@ public:
mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
virtual nsresult
GetServiceChannel(const nsAString& aObjectPath,
GetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
virtual bool
UpdateSdpRecords(const nsAString& aDeviceAddress,
BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode,

Просмотреть файл

@ -1928,7 +1928,8 @@ public:
for (uint32_t i = 0; i < mDeviceAddresses.Length(); i++) {
BluetoothValue v;
nsString objectPath = GetObjectPathFromAddress(sAdapterPath, mDeviceAddresses[i]);
nsString objectPath =
GetObjectPathFromAddress(sAdapterPath, mDeviceAddresses[i]);
if (!GetPropertiesInternal(objectPath, DBUS_DEVICE_IFACE, v)) {
errorStr.AssignLiteral("Getting properties failed!");
@ -2533,19 +2534,16 @@ BluetoothDBusService::Connect(const nsAString& aDeviceAddress,
if (aProfileId == BluetoothServiceClass::HANDSFREE) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Connect(
GetObjectPathFromAddress(sAdapterPath, aDeviceAddress), true, aRunnable);
hfp->Connect(aDeviceAddress, true, aRunnable);
} else if (aProfileId == BluetoothServiceClass::HEADSET) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Connect(
GetObjectPathFromAddress(sAdapterPath, aDeviceAddress), false, aRunnable);
hfp->Connect(aDeviceAddress, false, aRunnable);
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->Connect(
GetObjectPathFromAddress(sAdapterPath, aDeviceAddress), aRunnable);
opp->Connect(aDeviceAddress, aRunnable);
} else {
BluetoothValue v;
DispatchBluetoothReply(aRunnable, v, NS_LITERAL_STRING("UnknownProfileError"));
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING("UnknownProfileError"));
}
}
@ -2641,6 +2639,34 @@ private:
int mChannel;
};
class OnUpdateSdpRecordsRunnable : public nsRunnable
{
public:
OnUpdateSdpRecordsRunnable(const nsAString& aObjectPath,
BluetoothProfileManagerBase* aManager)
: mManager(aManager)
{
MOZ_ASSERT(!aObjectPath.IsEmpty());
MOZ_ASSERT(aManager);
mDeviceAddress = GetAddressFromObjectPath(aObjectPath);
}
nsresult
Run()
{
MOZ_ASSERT(NS_IsMainThread());
mManager->OnUpdateSdpRecords(mDeviceAddress);
return NS_OK;
}
private:
nsString mDeviceAddress;
BluetoothProfileManagerBase* mManager;
};
class OnGetServiceChannelRunnable : public nsRunnable
{
public:
@ -2715,14 +2741,16 @@ private:
};
nsresult
BluetoothDBusService::GetServiceChannel(const nsAString& aObjectPath,
BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
BluetoothProfileManagerBase* aManager)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBluetoothCommandThread);
nsRefPtr<nsRunnable> r(new GetServiceChannelRunnable(aObjectPath,
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
nsRefPtr<nsRunnable> r(new GetServiceChannelRunnable(objectPath,
aServiceUuid,
aManager));
@ -2733,6 +2761,43 @@ BluetoothDBusService::GetServiceChannel(const nsAString& aObjectPath,
return NS_OK;
}
static void
DiscoverServicesCallback(DBusMessage* aMsg, void* aData)
{
MOZ_ASSERT(!NS_IsMainThread());
nsRefPtr<OnUpdateSdpRecordsRunnable> r(
static_cast<OnUpdateSdpRecordsRunnable*>(aData));
NS_DispatchToMainThread(r);
}
bool
BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
BluetoothProfileManagerBase* aManager)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(aManager);
MOZ_ASSERT(mConnection);
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
// I choose to use raw pointer here because this is going to be passed as an
// argument into dbus_func_args_async() at once.
OnUpdateSdpRecordsRunnable* callbackRunnable =
new OnUpdateSdpRecordsRunnable(objectPath, aManager);
return dbus_func_args_async(mConnection,
-1,
DiscoverServicesCallback,
(void*)callbackRunnable,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE,
"DiscoverServices",
DBUS_TYPE_STRING, &EmptyCString(),
DBUS_TYPE_INVALID);
}
nsresult
BluetoothDBusService::GetScoSocket(const nsAString& aAddress,
bool aAuth,

Просмотреть файл

@ -85,10 +85,14 @@ public:
mozilla::ipc::UnixSocketConsumer* aConsumer);
virtual nsresult
GetServiceChannel(const nsAString& aObjectPath,
GetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
BluetoothProfileManagerBase* aManager);
virtual bool
UpdateSdpRecords(const nsAString& aDeviceAddress,
BluetoothProfileManagerBase* aManager);
virtual nsresult
CreatePairedDeviceInternal(const nsAString& aDeviceAddress,
int aTimeout,

Просмотреть файл

@ -693,7 +693,8 @@ ContactDB.prototype = {
}
},
_clearDispatcher: function CDB_clearDispatcher(aCursorId) {
clearDispatcher: function CDB_clearDispatcher(aCursorId) {
if (DEBUG) debug("clearDispatcher: " + aCursorId);
if (aCursorId in this._dispatcher) {
delete this._dispatcher[aCursorId];
}
@ -709,7 +710,7 @@ ContactDB.prototype = {
// object store again.
if (aCachedResults && aCachedResults.length > 0) {
let newTxnFn = this.newTxn.bind(this);
let clearDispatcherFn = this._clearDispatcher.bind(this, aCursorId);
let clearDispatcherFn = this.clearDispatcher.bind(this, aCursorId);
this._dispatcher[aCursorId] = new ContactDispatcher(aCachedResults, aFullContacts,
aSuccessCb, newTxnFn, clearDispatcherFn);
this._dispatcher[aCursorId].sendNow();

Просмотреть файл

@ -31,6 +31,7 @@ let ContactService = {
"Contact:Remove", "Contacts:RegisterForMessages",
"child-process-shutdown", "Contacts:GetRevision"];
this._children = [];
this._cursors = {};
this._messages.forEach(function(msgName) {
ppmm.addMessageListener(msgName, this);
}.bind(this));
@ -54,6 +55,8 @@ let ContactService = {
if (this._db)
this._db.close();
this._db = null;
this._children = null;
this._cursors = null;
},
assertPermission: function(aMessage, aPerm) {
@ -98,15 +101,24 @@ let ContactService = {
if (!this.assertPermission(aMessage, "contacts-read")) {
return null;
}
if (!this._cursors[mm]) {
this._cursors[mm] = [];
}
this._cursors[mm].push(msg.cursorId);
this._db.getAll(
function(aContacts) {
try {
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
if (aContacts === null) {
let index = this._cursors[mm].indexOf(msg.cursorId);
this._cursors[mm].splice(index, 1);
}
} catch (e) {
if (DEBUG) debug("Child is dead, DB should stop sending contacts");
throw e;
}
},
}.bind(this),
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Find:Return:KO", { errorMsg: aErrorMsg }); },
msg.findOptions, msg.cursorId);
break;
@ -188,6 +200,12 @@ let ContactService = {
if (DEBUG) debug("Unregister index: " + index);
this._children.splice(index, 1);
}
if (this._cursors[mm]) {
for (let id of this._cursors[mm]) {
this._db.clearDispatcher(id);
}
delete this._cursors[mm];
}
break;
default:
if (DEBUG) debug("WRONG MESSAGE NAME: " + aMessage.name);

Просмотреть файл

@ -408,6 +408,27 @@ let steps = [
}
},
clearDatabase,
addContacts,
function() {
if (!SpecialPowers.isMainProcess()) {
// We stop calling continue() intentionally here to see if the cursor gets
// cleaned up properly in the parent.
ok(true, "Leaking a cursor");
req = mozContacts.getAll({
sortBy: "familyName",
sortOrder: "ascending"
});
req.onsuccess = function(event) {
next();
};
req.onerror = onFailure;
} else {
next();
}
},
clearDatabase,
function() {
@ -422,8 +443,9 @@ function next() {
ok(false, "Shouldn't get here!");
return;
}
let i = index++;
try {
steps[index++]();
steps[i]();
} catch(ex) {
ok(false, "Caught exception", ex);
}

Просмотреть файл

@ -397,6 +397,10 @@ MobileConnection::GetCallBarringOption(const JS::Value& aOption,
{
*aRequest = nullptr;
if (!CheckPermission("mobileconnection")) {
return NS_OK;
}
if (!mProvider) {
return NS_ERROR_FAILURE;
}
@ -410,6 +414,10 @@ MobileConnection::SetCallBarringOption(const JS::Value& aOption,
{
*aRequest = nullptr;
if (!CheckPermission("mobileconnection")) {
return NS_OK;
}
if (!mProvider) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -30,6 +30,21 @@ function sendEmulatorCommand(cmd, callback) {
});
}
function setEmulatorOperatorNamesAndMccMnc(which, longName, shortName,
mcc, mnc, callback) {
let cmd = "operator set " + which + " " + longName + "," +
shortName + "," + mcc + mnc;
sendEmulatorCommand(cmd, function (result) {
let re = new RegExp("^" + longName + "," +
shortName + "," + mcc + mnc);
ok(result[which].match(re), "Long/short name and mcc/mnc should be changed.");
if (callback) {
window.setTimeout(callback, 0);
}
});
}
function setEmulatorOperatorNames(which, longName, shortName, callback) {
let cmd = "operator set " + which + " " + longName + "," + shortName;
sendEmulatorCommand(cmd, function (result) {
@ -87,13 +102,36 @@ function testMobileOperatorNames() {
doTestMobileOperatorNames("Mozilla", "", function () {
doTestMobileOperatorNames("", "B2G", function () {
doTestMobileOperatorNames("", "", function () {
doTestMobileOperatorNames("Android", "Android", testRoamingCheck);
doTestMobileOperatorNames("Android", "Android", testOperatorPLMNList);
});
});
});
});
}
function doTestOperatorPLMNList(mcc, mnc, expectedLongName,
expectedShortName, callback) {
log("Testing mcc = " + mcc + ", mnc = " + mnc + ":");
waitForVoiceChange(function () {
is(network.longName, expectedLongName, "network.longName");
is(network.shortName, expectedShortName, "network.shortName");
is(network.mcc, mcc, "network.mcc");
is(network.mnc, mnc, "network.mnc");
window.setTimeout(callback, 0);
});
setEmulatorOperatorNamesAndMccMnc(OPERATOR_HOME, "Android", "Android", mcc, mnc);
}
function testOperatorPLMNList() {
doTestOperatorPLMNList("123", "456", "Android", "Android", function() {
doTestOperatorPLMNList("310", "070", "AT&T", "", function() {
doTestOperatorPLMNList("310", "260", "Android", "Android", testRoamingCheck);
});
});
}
// See bug 797972 - B2G RIL: False roaming situation
//
// Steps to test:

Просмотреть файл

@ -1274,6 +1274,11 @@ RILContentHelper.prototype = {
handleEnumerateCalls: function handleEnumerateCalls(calls) {
debug("handleEnumerateCalls: " + JSON.stringify(calls));
let callback = this._enumerateTelephonyCallbacks.shift();
if (!calls.length) {
callback.enumerateCallStateComplete();
return;
}
for (let i in calls) {
let call = calls[i];
let keepGoing;
@ -1291,6 +1296,8 @@ RILContentHelper.prototype = {
break;
}
}
callback.enumerateCallStateComplete();
},
handleGetAvailableNetworks: function handleGetAvailableNetworks(message) {

Просмотреть файл

@ -19,12 +19,14 @@
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsTArrayHelpers.h"
#include "nsThreadUtils.h"
#include "TelephonyCall.h"
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
namespace {
@ -56,8 +58,27 @@ public:
}
};
class Telephony::EnumerationAck : public nsRunnable
{
nsRefPtr<Telephony> mTelephony;
public:
EnumerationAck(Telephony* aTelephony)
: mTelephony(aTelephony)
{
MOZ_ASSERT(mTelephony);
}
NS_IMETHOD Run()
{
mTelephony->NotifyCallsChanged(nullptr);
return NS_OK;
}
};
Telephony::Telephony()
: mActiveCall(nullptr), mCallsArray(nullptr), mRooted(false)
: mActiveCall(nullptr), mCallsArray(nullptr), mRooted(false),
mEnumerated(false)
{
if (!gTelephonyList) {
gTelephonyList = new TelephonyList();
@ -145,13 +166,15 @@ Telephony::NoteDialedCallFromOtherInstance(const nsAString& aNumber)
nsresult
Telephony::NotifyCallsChanged(TelephonyCall* aCall)
{
if (aCall->CallState() == nsITelephonyProvider::CALL_STATE_DIALING ||
aCall->CallState() == nsITelephonyProvider::CALL_STATE_ALERTING ||
aCall->CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED) {
NS_ASSERTION(!mActiveCall, "Already have an active call!");
mActiveCall = aCall;
} else if (mActiveCall && mActiveCall->CallIndex() == aCall->CallIndex()) {
mActiveCall = nullptr;
if (aCall) {
if (aCall->CallState() == nsITelephonyProvider::CALL_STATE_DIALING ||
aCall->CallState() == nsITelephonyProvider::CALL_STATE_ALERTING ||
aCall->CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED) {
NS_ASSERTION(!mActiveCall, "Already have an active call!");
mActiveCall = aCall;
} else if (mActiveCall && mActiveCall->CallIndex() == aCall->CallIndex()) {
mActiveCall = nullptr;
}
}
return DispatchCallEvent(NS_LITERAL_STRING("callschanged"), aCall);
@ -233,6 +256,8 @@ DOMCI_DATA(Telephony, Telephony)
NS_IMPL_ISUPPORTS1(Telephony::Listener, nsITelephonyListener)
// nsIDOMTelephony
NS_IMETHODIMP
Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
{
@ -362,7 +387,176 @@ Telephony::StopTone()
}
NS_IMPL_EVENT_HANDLER(Telephony, incoming)
NS_IMPL_EVENT_HANDLER(Telephony, callschanged)
NS_IMETHODIMP
Telephony::GetOncallschanged(JSContext* aCx, JS::Value* aValue)
{
GetEventHandler(nsGkAtoms::oncallschanged, aCx, aValue);
return NS_OK;
}
NS_IMETHODIMP
Telephony::SetOncallschanged(JSContext* aCx, const JS::Value& aValue)
{
JS::Value value;
GetEventHandler(nsGkAtoms::oncallschanged, aCx, &value);
if (aValue == value) {
// The event handler is being set to itself.
return NS_OK;
}
nsresult rv = SetEventHandler(nsGkAtoms::oncallschanged, aCx, aValue);
if (NS_FAILED(rv)) {
return rv;
}
// Fire oncallschanged on the next tick if the calls array is ready.
EnqueueEnumerationAck();
return NS_OK;
}
// nsIDOMEventTarget
NS_IMETHODIMP
Telephony::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture,
bool aWantsUntrusted, uint8_t aArgc)
{
nsresult rv = nsDOMEventTargetHelper::AddEventListener(aType, aListener,
aUseCapture,
aWantsUntrusted,
aArgc);
NS_ENSURE_SUCCESS(rv, rv);
if (aType.EqualsLiteral("callschanged")) {
// Fire oncallschanged on the next tick if the calls array is ready.
EnqueueEnumerationAck();
}
return NS_OK;
}
void
Telephony::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener, bool aUseCapture,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture,
aWantsUntrusted, aRv);
if (aRv.Failed()) {
return;
}
if (aType.EqualsLiteral("callschanged")) {
// Fire oncallschanged on the next tick if the calls array is ready.
EnqueueEnumerationAck();
}
}
NS_IMETHODIMP
Telephony::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture, bool aWantsUntrusted,
uint8_t aArgc)
{
nsresult rv = nsDOMEventTargetHelper::AddSystemEventListener(aType, aListener,
aUseCapture,
aWantsUntrusted,
aArgc);
NS_ENSURE_SUCCESS(rv, rv);
if (aType.EqualsLiteral("callschanged")) {
// Fire oncallschanged on the next tick if the calls array is ready.
EnqueueEnumerationAck();
}
return NS_OK;
}
NS_IMETHODIMP
Telephony::RemoveEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
return nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, false);
}
NS_IMETHODIMP
Telephony::RemoveSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture)
{
return nsDOMEventTargetHelper::RemoveSystemEventListener(aType, aListener,
aUseCapture);
}
NS_IMETHODIMP
Telephony::DispatchEvent(nsIDOMEvent* aEvt, bool* aRetval)
{
return nsDOMEventTargetHelper::DispatchEvent(aEvt, aRetval);
}
EventTarget*
Telephony::GetTargetForDOMEvent()
{
return nsDOMEventTargetHelper::GetTargetForDOMEvent();
}
EventTarget*
Telephony::GetTargetForEventTargetChain()
{
return nsDOMEventTargetHelper::GetTargetForEventTargetChain();
}
nsresult
Telephony::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
return nsDOMEventTargetHelper::PreHandleEvent(aVisitor);
}
nsresult
Telephony::WillHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return nsDOMEventTargetHelper::WillHandleEvent(aVisitor);
}
nsresult
Telephony::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return nsDOMEventTargetHelper::PostHandleEvent(aVisitor);
}
nsresult
Telephony::DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
return nsDOMEventTargetHelper::DispatchDOMEvent(aEvent, aDOMEvent,
aPresContext,
aEventStatus);
}
nsEventListenerManager*
Telephony::GetListenerManager(bool aMayCreate)
{
return nsDOMEventTargetHelper::GetListenerManager(aMayCreate);
}
nsIScriptContext*
Telephony::GetContextForEventHandlers(nsresult* aRv)
{
return nsDOMEventTargetHelper::GetContextForEventHandlers(aRv);
}
JSContext*
Telephony::GetJSContextForEventHandlers()
{
return nsDOMEventTargetHelper::GetJSContextForEventHandlers();
}
// nsITelephonyListener
NS_IMETHODIMP
Telephony::CallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
@ -440,6 +634,19 @@ Telephony::CallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
return NS_OK;
}
NS_IMETHODIMP
Telephony::EnumerateCallStateComplete()
{
MOZ_ASSERT(!mEnumerated);
mEnumerated = true;
if (NS_FAILED(NotifyCallsChanged(nullptr))) {
NS_WARNING("Failed to notify calls changed!");
}
return NS_OK;
}
NS_IMETHODIMP
Telephony::EnumerateCallState(uint32_t aCallIndex, uint16_t aCallState,
const nsAString& aNumber, bool aIsActive,
@ -506,7 +713,9 @@ nsresult
Telephony::DispatchCallEvent(const nsAString& aType,
nsIDOMTelephonyCall* aCall)
{
MOZ_ASSERT(aCall);
// We will notify enumeration being completed by firing oncallschanged.
// We only ever have a null call with that event type.
MOZ_ASSERT(aCall || aType.EqualsLiteral("callschanged"));
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMCallEvent(getter_AddRefs(event), this, nullptr, nullptr);
@ -520,6 +729,19 @@ Telephony::DispatchCallEvent(const nsAString& aType,
return DispatchTrustedEvent(callEvent);
}
void
Telephony::EnqueueEnumerationAck()
{
if (!mEnumerated) {
return;
}
nsCOMPtr<nsIRunnable> task = new EnumerationAck(this);
if (NS_FAILED(NS_DispatchToCurrentThread(task))) {
NS_WARNING("Failed to dispatch to current thread!");
}
}
nsresult
NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony)
{

Просмотреть файл

@ -30,6 +30,9 @@ class Telephony : public nsDOMEventTargetHelper,
*/
class Listener;
class EnumerationAck;
friend class EnumerationAck;
nsCOMPtr<nsITelephonyProvider> mProvider;
nsRefPtr<Listener> mListener;
@ -41,17 +44,25 @@ class Telephony : public nsDOMEventTargetHelper,
JSObject* mCallsArray;
bool mRooted;
bool mEnumerated;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMTELEPHONY
NS_DECL_NSITELEPHONYLISTENER
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
NS_DECL_NSIDOMEVENTTARGET
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
Telephony,
nsDOMEventTargetHelper)
using nsDOMEventTargetHelper::RemoveEventListener;
virtual void AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
static already_AddRefed<Telephony>
Create(nsPIDOMWindow* aOwner, nsITelephonyProvider* aProvider);
@ -106,6 +117,9 @@ private:
nsresult
DispatchCallEvent(const nsAString& aType,
nsIDOMTelephonyCall* aCall);
void
EnqueueEnumerationAck();
};
END_TELEPHONY_NAMESPACE

Просмотреть файл

@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, uuid(bde19ba2-83c8-4df7-a014-28fe71535527)]
[scriptable, uuid(37fde795-7ff4-40fd-925b-3ebc07ba0cd1)]
interface nsITelephonyListener : nsISupports
{
/**
@ -30,6 +30,12 @@ interface nsITelephonyListener : nsISupports
in boolean isOutgoing,
in boolean isEmergency);
/**
* Called when enumeration asked by nsITelephonyProvider::enumerateCalls
* is completed.
*/
void enumerateCallStateComplete();
/**
* Called when nsITelephonyProvider is asked to enumerate the current
* telephony call state (nsITelephonyProvider::enumerateCalls). This is