Merge mozilla-central and b2g-inbound

This commit is contained in:
Ed Morley 2013-09-06 12:32:33 +01:00
Родитель afcdd911d2 19fc94eb8e
Коммит 1717198314
103 изменённых файлов: 4685 добавлений и 2557 удалений

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

@ -892,6 +892,8 @@ function getDocumentEncoder(element) {
.createInstance(Ci.nsIDocumentEncoder);
let flags = Ci.nsIDocumentEncoder.SkipInvisibleContent |
Ci.nsIDocumentEncoder.OutputRaw |
// Bug 902847. Don't trim trailing spaces of a line.
Ci.nsIDocumentEncoder.OutputDontRemoveLineEndingSpaces |
Ci.nsIDocumentEncoder.OutputLFLineBreak |
Ci.nsIDocumentEncoder.OutputNonTextContentAsPlaceholder;
encoder.init(element.ownerDocument, "text/plain", flags);

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

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
"use strict;"
const Cc = Components.classes;
const Ci = Components.interfaces;
@ -21,65 +21,47 @@ XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
});
#endif
// Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
// is resolved this helper could be removed.
var SettingsListener = {
// Timer to remove the lock.
_timer: null,
_callbacks: {},
// lock stores here
_lock: null,
/**
* getSettingsLock: create a lock or retrieve one that we saved.
* mozSettings.createLock() is expensive and lock should be reused
* whenever possible.
*/
getSettingsLock: function sl_getSettingsLock() {
// Each time there is a getSettingsLock call, we postpone the removal.
clearTimeout(this._timer);
this._timer = setTimeout((function() {
this._lock = null;
}).bind(this), 0);
// If there is a lock present we return that.
if (this._lock) {
return this._lock;
init: function sl_init() {
if ('mozSettings' in navigator && navigator.mozSettings) {
navigator.mozSettings.onsettingchange = this.onchange.bind(this);
}
},
// If there isn't we create a new one.
let settings = window.navigator.mozSettings;
return (this._lock = settings.createLock());
onchange: function sl_onchange(evt) {
var callback = this._callbacks[evt.settingName];
if (callback) {
callback(evt.settingValue);
}
},
observe: function sl_observe(name, defaultValue, callback) {
let settings = window.navigator.mozSettings;
let req;
try {
req = this.getSettingsLock().get(name);
} catch (e) {
// It is possible (but rare) for getSettingsLock() to return
// a SettingsLock object that is no longer valid.
// Until https://bugzilla.mozilla.org/show_bug.cgi?id=793239
// is fixed, we just catch the resulting exception and try
// again with a fresh lock
console.warn('Stale lock in settings.js.',
'See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');
this._lock = null;
req = this.getSettingsLock().get(name);
var settings = window.navigator.mozSettings;
if (!settings) {
window.setTimeout(function() { callback(defaultValue); });
return;
}
if (!callback || typeof callback !== 'function') {
throw new Error('Callback is not a function');
}
var req = settings.createLock().get(name);
req.addEventListener('success', (function onsuccess() {
callback(typeof(req.result[name]) != 'undefined' ?
req.result[name] : defaultValue);
}));
settings.addObserver(name, function settingChanged(evt) {
callback(evt.settingValue);
});
this._callbacks[name] = callback;
}
};
SettingsListener.init();
// =================== Console ======================
SettingsListener.observe('debug.console.enabled', true, function(value) {
@ -446,6 +428,8 @@ SettingsListener.observe('app.reportCrashes', 'ask', function(value) {
} else {
Services.prefs.clearUserPref('app.reportCrashes');
}
// This preference is consulted during startup.
Services.prefs.savePrefFile(null);
});
// ================ Updates ================

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

@ -1,4 +1,4 @@
{
"revision": "1bb5a08dd1a7b974168dfd7f03bb1246c592d304",
"revision": "3a11e24a45501f1fcad106ef588fcc7262722644",
"repo_path": "/integration/gaia-central"
}

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

@ -164,7 +164,6 @@
@BINPATH@/components/dom_base.xpt
@BINPATH@/components/dom_system.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_voicemail.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_gonk.xpt
@ -203,6 +202,7 @@
@BINPATH@/components/dom_mobilemessage.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_threads.xpt
@BINPATH@/components/dom_traversal.xpt
@BINPATH@/components/dom_views.xpt
@ -460,6 +460,8 @@
@BINPATH@/components/RadioInterfaceLayer.js
@BINPATH@/components/MmsService.manifest
@BINPATH@/components/MmsService.js
@BINPATH@/components/SmsService.manifest
@BINPATH@/components/SmsService.js
@BINPATH@/components/RILContentHelper.js
@BINPATH@/components/MobileMessageDatabaseService.manifest
@BINPATH@/components/MobileMessageDatabaseService.js
@ -471,6 +473,8 @@
@BINPATH@/components/NetworkStatsManager.manifest
@BINPATH@/components/NetworkInterfaceListService.manifest
@BINPATH@/components/NetworkInterfaceListService.js
@BINPATH@/components/TelephonyProvider.manifest
@BINPATH@/components/TelephonyProvider.js
#endif
#ifdef MOZ_ENABLE_DBUS
@BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@

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

@ -176,7 +176,6 @@
@BINPATH@/components/dom_base.xpt
@BINPATH@/components/dom_system.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_voicemail.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_gonk.xpt
@ -212,6 +211,7 @@
@BINPATH@/components/dom_mobilemessage.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_traversal.xpt
#ifdef MOZ_WEBSPEECH
@BINPATH@/components/dom_webspeechrecognition.xpt
@ -446,6 +446,8 @@
@BINPATH@/components/RadioInterfaceLayer.js
@BINPATH@/components/MmsService.manifest
@BINPATH@/components/MmsService.js
@BINPATH@/components/SmsService.manifest
@BINPATH@/components/SmsService.js
@BINPATH@/components/RILContentHelper.js
@BINPATH@/components/MobileMessageDatabaseService.manifest
@BINPATH@/components/MobileMessageDatabaseService.js

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

@ -222,6 +222,11 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputNonTextContentAsPlaceholder = (1 << 23);
/**
* Don't Strip ending spaces from a line (only for serializing to plaintext).
*/
const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

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

@ -1373,6 +1373,7 @@ nsPlainTextSerializer::EndLine(bool aSoftlinebreak, bool aBreakBySpace)
* signed messages according to the OpenPGP standard (RFC 2440).
*/
if (!(mFlags & nsIDocumentEncoder::OutputPreformatted) &&
!(mFlags & nsIDocumentEncoder::OutputDontRemoveLineEndingSpaces) &&
(aSoftlinebreak ||
!(mCurrentLine.EqualsLiteral("-- ") || mCurrentLine.EqualsLiteral("- -- ")))) {
// Remove spaces from the end of the line.

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

@ -580,6 +580,7 @@ MOCHITEST_FILES_C= \
test_processing_instruction_update_stylesheet.xhtml \
test_bug907892.html \
file_bug907892.html \
test_bug902847.html \
$(NULL)
# OOP tests don't work on Windows (bug 763081) or native-fennec

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

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=902847
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 902847</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
function testPaintextSerializerWithPlaceHolder() {
const de = SpecialPowers.Ci.nsIDocumentEncoder;
const Cc = SpecialPowers.Cc;
// Create a plaintext encoder.
var encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
.createInstance(de);
var flags = de.OutputRaw |
de.OutputLFLineBreak |
de.OutputDontRemoveLineEndingSpaces;
encoder.init(document, "text/plain", flags);
function toPlaintext(id) {
var element = document.getElementById(id);
var range = document.createRange();
range.selectNodeContents(element);
encoder.setRange(range);
return encoder.encodeToString().replace('\n', '\\n', 'g')
.replace('\r', '\\r', 'g');
}
// Test cases.
is(toPlaintext("case1"), "Hello \\nboy!", "Case 1 failed.");
is(toPlaintext("case2"), "Hello \\nboy!", "Case 2 failed.");
is(toPlaintext("case3"), "Hello \\nboy!", "Case 3 failed.");
is(toPlaintext("case4"), "Hello \\nboy!", "Case 4 failed.");
SimpleTest.finish();
}
addLoadEvent(testPaintextSerializerWithPlaceHolder);
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=902847">Mozilla Bug 902847</a>
<p id="display"></p>
<div id="content">
<p id="case1">Hello <br>boy!</p>
<p id="case2">Hello <br>boy!</p>
<p id="case3">Hello&nbsp;<br>boy!</p>
<p id="case4">Hello&nbsp;&nbsp;<br>boy!</p>
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -54,7 +54,7 @@
#include "MediaManager.h"
#endif
#ifdef MOZ_B2G_RIL
#include "Telephony.h"
#include "mozilla/dom/telephony/Telephony.h"
#endif
#ifdef MOZ_B2G_BT
#include "BluetoothManager.h"

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

@ -168,12 +168,12 @@ DOMInterfaces = {
'CallEvent': {
'nativeType': 'mozilla::dom::telephony::CallEvent',
'headerFile': 'CallEvent.h',
'headerFile': 'mozilla/dom/telephony/CallEvent.h',
},
'CallsList': {
'nativeType': 'mozilla::dom::telephony::CallsList',
'headerFile': 'CallsList.h',
'headerFile': 'mozilla/dom/telephony/CallsList.h',
},
'CameraControl': {
@ -1162,17 +1162,17 @@ DOMInterfaces = {
'Telephony' : {
'nativeType': 'mozilla::dom::telephony::Telephony',
'headerFile': 'Telephony.h',
'headerFile': 'mozilla/dom/telephony/Telephony.h',
},
'TelephonyCall' : {
'nativeType': 'mozilla::dom::telephony::TelephonyCall',
'headerFile': 'TelephonyCall.h',
'headerFile': 'mozilla/dom/telephony/TelephonyCall.h',
},
'TelephonyCallGroup' : {
'nativeType': 'mozilla::dom::telephony::TelephonyCallGroup',
'headerFile': 'TelephonyCallGroup.h',
'headerFile': 'mozilla/dom/telephony/TelephonyCallGroup.h',
},
'Text': {

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

@ -9,6 +9,7 @@
#include "BluetoothA2dpManager.h"
#include "BluetoothCommon.h"
#include "BluetoothProfileController.h"
#include "BluetoothService.h"
#include "BluetoothSocket.h"
#include "BluetoothUtils.h"
@ -78,8 +79,8 @@ void
BluetoothA2dpManager::ResetA2dp()
{
mA2dpConnected = false;
mPlaying = false;
mSinkState = SinkState::SINK_DISCONNECTED;
mController = nullptr;
}
void
@ -140,113 +141,195 @@ BluetoothA2dpManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
sInShutdown = true;
Disconnect();
Disconnect(nullptr);
sBluetoothA2dpManager = nullptr;
}
bool
BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress)
void
BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
NS_ENSURE_FALSE(sInShutdown, false);
NS_ENSURE_FALSE(mA2dpConnected, false);
mDeviceAddress = aDeviceAddress;
MOZ_ASSERT(aController && !mController);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, false);
nsresult rv = bs->SendSinkMessage(aDeviceAddress,
NS_LITERAL_STRING("Connect"));
if (!bs || sInShutdown) {
aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
return NS_SUCCEEDED(rv);
if (mA2dpConnected) {
aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
return;
}
mDeviceAddress = aDeviceAddress;
mController = aController;
bs->SendSinkMessage(aDeviceAddress, NS_LITERAL_STRING("Connect"));
}
void
BluetoothA2dpManager::Disconnect()
BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
{
NS_ENSURE_TRUE_VOID(mA2dpConnected);
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
}
return;
}
if (!mA2dpConnected) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
}
return;
}
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
MOZ_ASSERT(!mController);
mController = aController;
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
bs->SendSinkMessage(mDeviceAddress, NS_LITERAL_STRING("Disconnect"));
}
void
BluetoothA2dpManager::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnConnect(aErrorStr);
mController = nullptr;
}
void
BluetoothA2dpManager::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnDisconnect(aErrorStr);
mController = nullptr;
}
/* HandleSinkPropertyChanged update sink state in A2dp
*
* Possible values: "disconnected", "disconnecting",
* "connecting", "connected",
* "playing"
*
* 1. "disconnected" -> "connecting"
* Either an incoming or outgoing connection attempt ongoing
* 2. "connecting" -> "disconnected"
* Connection attempt failed
* 3. "connecting" -> "connected"
* Successfully connected
* 4. "connected" -> "playing"
* Audio stream active
* 5. "playing" -> "connected"
* Audio stream suspended
* 6. "connected" -> "disconnected"
* "playing" -> "disconnected"
* Disconnected from the remote device
* 7. "disconnecting" -> "disconnected"
* Disconnected from local
*/
void
BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const nsString& address = aSignal.path();
const InfallibleTArray<BluetoothNamedValue>& arr =
aSignal.value().get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() == 1);
/**
* There are three properties:
* - "State": a string
* - "Connected": a boolean value
* - "Playing": a boolean value
*
* Note that only "State" is handled in this function.
*/
const nsString& name = arr[0].name();
NS_ENSURE_TRUE_VOID(name.EqualsLiteral("State"));
const BluetoothValue& value = arr[0].value();
if (name.EqualsLiteral("Connected")) {
// Indicates if a stream is setup to a A2DP sink on the remote device.
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
MOZ_ASSERT(mA2dpConnected != value.get_bool());
MOZ_ASSERT(value.type() == BluetoothValue::TnsString);
SinkState prevState = mSinkState;
mSinkState = StatusStringToSinkState(value.get_nsString());
mA2dpConnected = value.get_bool();
NotifyConnectionStatusChanged();
DispatchConnectionStatusChanged();
} else if (name.EqualsLiteral("Playing")) {
// Indicates if a stream is active to a A2DP sink on the remote device.
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
MOZ_ASSERT(mPlaying != value.get_bool());
NS_ENSURE_TRUE_VOID(mSinkState != prevState);
mPlaying = value.get_bool();
} else if (name.EqualsLiteral("State")) {
MOZ_ASSERT(value.type() == BluetoothValue::TnsString);
MOZ_ASSERT(mSinkState != StatusStringToSinkState(value.get_nsString()));
switch(mSinkState) {
case SinkState::SINK_CONNECTING:
// case 1: Either an incoming or outgoing connection attempt ongoing
MOZ_ASSERT(prevState == SinkState::SINK_DISCONNECTED);
break;
case SinkState::SINK_PLAYING:
// case 4: Audio stream active
MOZ_ASSERT(prevState == SinkState::SINK_CONNECTED);
break;
case SinkState::SINK_CONNECTED:
// case 5: Audio stream suspended
if (prevState == SinkState::SINK_PLAYING) {
break;
}
// case 3: Successfully connected
MOZ_ASSERT(prevState == SinkState::SINK_CONNECTING);
HandleSinkStateChanged(StatusStringToSinkState(value.get_nsString()));
} else {
NS_WARNING("Unknown sink property");
mA2dpConnected = true;
mDeviceAddress = address;
NotifyConnectionStatusChanged();
DispatchConnectionStatusChanged();
OnConnect(EmptyString());
break;
case SinkState::SINK_DISCONNECTED:
// XXX
// case 2: Connection attempt failed
if (prevState == SinkState::SINK_CONNECTING) {
OnConnect(NS_LITERAL_STRING("A2dpConnectionError"));
break;
}
// case 6: Disconnected from the remote device
// case 7: Disconnected from local
MOZ_ASSERT(prevState == SinkState::SINK_CONNECTED ||
prevState == SinkState::SINK_PLAYING ||
prevState == SinkState::SINK_DISCONNECTING);
mA2dpConnected = false;
NotifyConnectionStatusChanged();
DispatchConnectionStatusChanged();
mDeviceAddress.Truncate();
// case 7 only
if (prevState == SinkState::SINK_DISCONNECTING) {
OnDisconnect(EmptyString());
}
break;
}
}
/* HandleSinkStateChanged updates sink state in A2dp
*
* Possible values: "disconnected", "connecting", "connected", "playing"
*
* 1. "disconnected" -> "connecting"
* Either an incoming or outgoing connection attempt ongoing
* 2. "connecting" -> "disconnected"
* Connection attempt failed
* 3. "connecting" -> "connected"
* Successfully connected
* 4. "connected" -> "playing"
* Audio stream active
* 5. "playing" -> "connected"
* Audio stream suspended
* 6. "connected" -> "disconnected"
* "playing" -> "disconnected"
* Disconnected from the remote device
* 7. "disconnecting" -> "disconnected"
* Disconnected from local
*/
void
BluetoothA2dpManager::HandleSinkStateChanged(SinkState aState)
{
MOZ_ASSERT_IF(aState == SinkState::SINK_CONNECTED,
mSinkState == SinkState::SINK_CONNECTING ||
mSinkState == SinkState::SINK_PLAYING);
MOZ_ASSERT_IF(aState == SinkState::SINK_PLAYING,
mSinkState == SinkState::SINK_CONNECTED);
if (aState == SinkState::SINK_DISCONNECTED) {
mDeviceAddress.Truncate();
}
mSinkState = aState;
}
void
BluetoothA2dpManager::DispatchConnectionStatusChanged()
{

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

@ -31,17 +31,20 @@ public:
void ResetA2dp();
void ResetAvrcp();
// Member functions inherited from parent class BluetoothProfileManagerBase
// The following functions are inherited from BluetoothProfileManagerBase
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
virtual void Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void Disconnect(BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void OnConnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
virtual void OnDisconnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
// A2DP member functions
bool Connect(const nsAString& aDeviceAddress);
void Disconnect();
void HandleSinkPropertyChanged(const BluetoothSignal& aSignal);
// AVRCP member functions
@ -67,17 +70,16 @@ private:
BluetoothA2dpManager();
bool Init();
void HandleSinkStateChanged(SinkState aState);
void HandleShutdown();
void DispatchConnectionStatusChanged();
void NotifyConnectionStatusChanged();
nsString mDeviceAddress;
BluetoothProfileController* mController;
// A2DP data member
bool mA2dpConnected;
bool mPlaying;
SinkState mSinkState;
// AVRCP data member

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

@ -471,7 +471,7 @@ BluetoothAdapter::SetDiscoverableTimeout(uint32_t aDiscoverableTimeout, ErrorRes
}
already_AddRefed<DOMRequest>
BluetoothAdapter::GetConnectedDevices(uint16_t aProfileId, ErrorResult& aRv)
BluetoothAdapter::GetConnectedDevices(uint16_t aServiceUuid, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
@ -490,7 +490,7 @@ BluetoothAdapter::GetConnectedDevices(uint16_t aProfileId, ErrorResult& aRv)
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsresult rv = bs->GetConnectedDevicePropertiesInternal(aProfileId, results);
nsresult rv = bs->GetConnectedDevicePropertiesInternal(aServiceUuid, results);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
@ -664,8 +664,9 @@ BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
}
already_AddRefed<DOMRequest>
BluetoothAdapter::Connect(const nsAString& aDeviceAddress,
uint16_t aProfileId, ErrorResult& aRv)
BluetoothAdapter::Connect(BluetoothDevice& aDevice,
const Optional<short unsigned int>& aServiceUuid,
ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
@ -677,18 +678,28 @@ BluetoothAdapter::Connect(const nsAString& aDeviceAddress,
nsRefPtr<BluetoothVoidReplyRunnable> results =
new BluetoothVoidReplyRunnable(request);
nsAutoString address;
aDevice.GetAddress(address);
uint32_t deviceClass = aDevice.Class();
uint16_t serviceUuid = 0;
if (aServiceUuid.WasPassed()) {
serviceUuid = aServiceUuid.Value();
}
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bs->Connect(aDeviceAddress, aProfileId, results);
bs->Connect(address, deviceClass, serviceUuid, results);
return request.forget();
}
already_AddRefed<DOMRequest>
BluetoothAdapter::Disconnect(uint16_t aProfileId, ErrorResult& aRv)
BluetoothAdapter::Disconnect(BluetoothDevice& aDevice,
const Optional<short unsigned int>& aServiceUuid,
ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
@ -700,12 +711,19 @@ BluetoothAdapter::Disconnect(uint16_t aProfileId, ErrorResult& aRv)
nsRefPtr<BluetoothVoidReplyRunnable> results =
new BluetoothVoidReplyRunnable(request);
nsAutoString address;
aDevice.GetAddress(address);
uint16_t serviceUuid = 0;
if (aServiceUuid.WasPassed()) {
serviceUuid = aServiceUuid.Value();
}
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
bs->Disconnect(aProfileId, results);
bs->Disconnect(address, serviceUuid, results);
return request.forget();
}

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

@ -115,12 +115,14 @@ public:
ErrorResult& aRv);
already_AddRefed<DOMRequest>
Connect(const nsAString& aDeviceAddress, uint16_t aProfile,
ErrorResult& aRv);
Connect(BluetoothDevice& aDevice,
const Optional<short unsigned int>& aServiceUuid, ErrorResult& aRv);
already_AddRefed<DOMRequest>
Disconnect(uint16_t aProfile, ErrorResult& aRv);
Disconnect(BluetoothDevice& aDevice,
const Optional<short unsigned int>& aServiceUuid,
ErrorResult& aRv);
already_AddRefed<DOMRequest>
GetConnectedDevices(uint16_t aProfile, ErrorResult& aRv);
GetConnectedDevices(uint16_t aServiceUuid, ErrorResult& aRv);
already_AddRefed<DOMRequest>
SendFile(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob,

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

@ -8,7 +8,7 @@
#include "BluetoothHfpManager.h"
#include "BluetoothA2dpManager.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothSocket.h"
@ -358,6 +358,8 @@ BluetoothHfpManager::Reset()
// Please see Bug 878728 for more information.
mBSIR = false;
mController = nullptr;
ResetCallArray();
}
@ -657,7 +659,7 @@ BluetoothHfpManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
sInShutdown = true;
Disconnect();
Disconnect(nullptr);
DisconnectSco();
sBluetoothHfpManager = nullptr;
}
@ -1000,43 +1002,38 @@ respond_with_ok:
void
BluetoothHfpManager::Connect(const nsAString& aDeviceAddress,
const bool aIsHandsfree,
BluetoothReplyRunnable* aRunnable)
BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aController && !mController);
BluetoothService* bs = BluetoothService::Get();
if (!bs || sInShutdown) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
if (mSocket) {
if (mDeviceAddress == aDeviceAddress) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
} else {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT));
aController->OnConnect(NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT));
}
return;
}
mNeedsUpdatingSdpRecords = true;
mIsHandsfree = aIsHandsfree;
mIsHandsfree = !IS_HEADSET(aController->GetCod());
nsString uuid;
if (aIsHandsfree) {
if (mIsHandsfree) {
BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid);
} else {
BluetoothUuidHelper::GetString(BluetoothServiceClass::HEADSET, uuid);
}
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
aController->OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
return;
}
@ -1051,9 +1048,7 @@ BluetoothHfpManager::Connect(const nsAString& aDeviceAddress,
mHeadsetSocket = nullptr;
}
MOZ_ASSERT(!mRunnable);
mRunnable = aRunnable;
mController = aController;
mSocket =
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
}
@ -1103,16 +1098,22 @@ BluetoothHfpManager::Listen()
}
void
BluetoothHfpManager::Disconnect()
BluetoothHfpManager::Disconnect(BluetoothProfileController* aController)
{
if (mSocket) {
mSocket->Disconnect();
mSocket = nullptr;
MOZ_ASSERT(NS_IsMainThread());
if (!mSocket) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
}
return;
}
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE_VOID(a2dp);
a2dp->Disconnect();
MOZ_ASSERT(!mController);
mController = aController;
mSocket->Disconnect();
mSocket = nullptr;
}
bool
@ -1450,7 +1451,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
}
void
BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
{
MOZ_ASSERT(aSocket);
@ -1482,19 +1483,10 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
}
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE_VOID(provider);
provider->EnumerateCalls(mListener->GetListener());
// For active connection request, we need to reply the DOMRequest
if (mRunnable) {
BluetoothValue v = true;
nsString errorStr;
DispatchBluetoothReply(mRunnable, v, errorStr);
mRunnable = nullptr;
}
mFirstCKPD = true;
// Cache device path for NotifySettings() since we can't get socket address
@ -1505,13 +1497,11 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
ListenSco();
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE_VOID(a2dp);
a2dp->Connect(mDeviceAddress);
OnConnect(EmptyString());
}
void
BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
BluetoothHfpManager::OnSocketConnectError(BluetoothSocket* aSocket)
{
// Failed to create a SCO socket
if (aSocket == mScoSocket) {
@ -1519,25 +1509,14 @@ BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
return;
}
// For active connection request, we need to reply the DOMRequest
if (mRunnable) {
NS_NAMED_LITERAL_STRING(replyError,
"Failed to connect with a bluetooth headset!");
DispatchBluetoothReply(mRunnable, BluetoothValue(), replyError);
mRunnable = nullptr;
}
mSocket = nullptr;
mHandsfreeSocket = nullptr;
mHeadsetSocket = nullptr;
// If connecting for some reason didn't work, restart listening
Listen();
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
}
void
BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
BluetoothHfpManager::OnSocketDisconnect(BluetoothSocket* aSocket)
{
MOZ_ASSERT(aSocket);
@ -1552,12 +1531,12 @@ BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
return;
}
mSocket = nullptr;
DisconnectSco();
Listen();
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
OnDisconnect(EmptyString());
Reset();
}
@ -1581,11 +1560,7 @@ BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
// 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();
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
}
}
@ -1596,7 +1571,6 @@ BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
@ -1608,22 +1582,14 @@ BluetoothHfpManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
mNeedsUpdatingSdpRecords = false;
bs->UpdateSdpRecords(aDeviceAddress, this);
} else {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
}
return;
}
if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) {
DispatchBluetoothReply(mRunnable, v,
NS_LITERAL_STRING("SocketConnectionError"));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
}
}
@ -1773,4 +1739,44 @@ BluetoothHfpManager::IsScoConnected()
return false;
}
void
BluetoothHfpManager::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
// When we failed to create a socket, restart listening.
if (!aErrorStr.IsEmpty()) {
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.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnConnect(aErrorStr);
mController = nullptr;
}
void
BluetoothHfpManager::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
// Start listening
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.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnDisconnect(aErrorStr);
mController = nullptr;
}
NS_IMPL_ISUPPORTS1(BluetoothHfpManager, nsIObserver)

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

@ -61,22 +61,26 @@ public:
static BluetoothHfpManager* Get();
~BluetoothHfpManager();
// The following functions are inherited from BluetoothSocketObserver
virtual void ReceiveSocketData(
BluetoothSocket* aSocket,
nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
// The following functions are inherited from BluetoothProfileManagerBase
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void Disconnect(BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void OnConnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
virtual void OnDisconnect(const nsAString& AErrorStr) MOZ_OVERRIDE;
void Connect(const nsAString& aDeviceAddress,
const bool aIsHandsfree,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
bool Listen();
bool ConnectSco(BluetoothReplyRunnable* aRunnable = nullptr);
bool DisconnectSco();
@ -148,6 +152,7 @@ private:
nsTArray<Call> mCurrentCallArray;
nsAutoPtr<BluetoothTelephonyListener> mListener;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
BluetoothProfileController* mController;
nsRefPtr<BluetoothReplyRunnable> mScoRunnable;
// If a connection has been established, mSocket will be the socket

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

@ -10,6 +10,7 @@
#include "BluetoothCommon.h"
#include "BluetoothService.h"
#include "BluetoothProfileController.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
@ -43,6 +44,7 @@ BluetoothHidManager::Observe(nsISupports* aSubject,
BluetoothHidManager::BluetoothHidManager()
: mConnected(false)
, mController(nullptr)
{
}
@ -97,51 +99,101 @@ BluetoothHidManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
sInShutdown = true;
Disconnect();
Disconnect(nullptr);
sBluetoothHidManager = nullptr;
}
bool
void
BluetoothHidManager::Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
NS_ENSURE_FALSE(sInShutdown, false);
NS_ENSURE_FALSE(mConnected, false);
mDeviceAddress = aDeviceAddress;
MOZ_ASSERT(aController && !mController);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, false);
nsresult rv = bs->SendInputMessage(aDeviceAddress,
NS_LITERAL_STRING("Connect"),
aRunnable);
if (!bs || sInShutdown) {
aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
return NS_SUCCEEDED(rv);
if (mConnected) {
aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
return;
}
mDeviceAddress = aDeviceAddress;
mController = aController;
bs->SendInputMessage(aDeviceAddress, NS_LITERAL_STRING("Connect"));
}
void
BluetoothHidManager::Disconnect()
BluetoothHidManager::Disconnect(BluetoothProfileController* aController)
{
NS_ENSURE_TRUE_VOID(mConnected);
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
bs->SendInputMessage(mDeviceAddress,
NS_LITERAL_STRING("Disconnect"),
nullptr);
if (!bs) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
}
return;
}
if (!mConnected) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
}
return;
}
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
MOZ_ASSERT(!mController);
mController = aController;
bs->SendInputMessage(mDeviceAddress, NS_LITERAL_STRING("Disconnect"));
}
bool BluetoothHidManager::IsConnected()
void
BluetoothHidManager::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnConnect(aErrorStr);
mController = nullptr;
}
void
BluetoothHidManager::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnDisconnect(aErrorStr);
mController = nullptr;
}
bool
BluetoothHidManager::IsConnected()
{
return mConnected;
}
void BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal& aSignal)
void
BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal& aSignal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
@ -159,6 +211,11 @@ void BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal& aSig
mConnected = value.get_bool();
NotifyStatusChanged();
if (mConnected) {
OnConnect(EmptyString());
} else {
OnDisconnect(EmptyString());
}
}
}

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

@ -23,16 +23,20 @@ public:
static BluetoothHidManager* Get();
~BluetoothHidManager();
// The following functions are inherited from BluetoothProfileManagerBase
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
virtual void Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void Disconnect(BluetoothProfileController* aController)
MOZ_OVERRIDE;
virtual void OnConnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
virtual void OnDisconnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
bool Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
void HandleInputPropertyChanged(const BluetoothSignal& aSignal);
private:
@ -46,6 +50,7 @@ private:
// data member
bool mConnected;
nsString mDeviceAddress;
BluetoothProfileController* mController;
};
END_BLUETOOTH_NAMESPACE

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

@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "BluetoothOppManager.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothSocket.h"
@ -176,6 +177,7 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
, mSentFileLength(0)
, mWaitingToSendPutFinal(false)
, mCurrentBlobIndex(-1)
, mController(nullptr)
{
mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
}
@ -228,24 +230,22 @@ BluetoothOppManager::Get()
void
BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aController && !mController);
BluetoothService* bs = BluetoothService::Get();
if (!bs || sInShutdown) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
if (mSocket) {
if (mConnectedDeviceAddress == aDeviceAddress) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
} else {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT));
aController->OnConnect(NS_LITERAL_STRING(ERR_REACHED_CONNECTION_LIMIT));
}
return;
}
@ -256,8 +256,7 @@ BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
BluetoothUuidHelper::GetString(BluetoothServiceClass::OBJECT_PUSH, uuid);
if (NS_FAILED(bs->GetServiceChannel(aDeviceAddress, uuid, this))) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
aController->OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
return;
}
@ -272,20 +271,26 @@ BluetoothOppManager::Connect(const nsAString& aDeviceAddress,
mL2capSocket = nullptr;
}
MOZ_ASSERT(!mRunnable);
mRunnable = aRunnable;
mController = aController;
mSocket =
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
}
void
BluetoothOppManager::Disconnect()
BluetoothOppManager::Disconnect(BluetoothProfileController* aController)
{
if (mSocket) {
mSocket->Disconnect();
mSocket = nullptr;
if (!mSocket) {
if (aController) {
aController->OnDisconnect(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
}
return;
}
MOZ_ASSERT(!mController);
mController = aController;
mSocket->Disconnect();
mSocket = nullptr;
}
void
@ -293,7 +298,7 @@ BluetoothOppManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
sInShutdown = true;
Disconnect();
Disconnect(nullptr);
sBluetoothOppManager = nullptr;
}
@ -446,7 +451,7 @@ BluetoothOppManager::AfterOppConnected()
// If we fail to get a mount lock, abort this transaction
// Directly sending disconnect-request is better than abort-request
NS_WARNING("BluetoothOPPManager couldn't get a mount lock!");
Disconnect();
Disconnect(nullptr);
}
}
@ -1343,7 +1348,7 @@ BluetoothOppManager::NotifyAboutFileChange()
}
void
BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket)
BluetoothOppManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
{
MOZ_ASSERT(aSocket);
@ -1351,8 +1356,7 @@ BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket)
* If the created connection is an inbound connection, close another server
* socket because currently only one file-transfer session is allowed. After
* that, we need to make sure that both server socket would be nulled out.
* As for outbound connections, we do nothing since sockets have been already
* handled in function Connect().
* As for outbound connections, we just notify the controller that it's done.
*/
if (aSocket == mRfcommSocket) {
MOZ_ASSERT(!mSocket);
@ -1368,38 +1372,24 @@ BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket)
mRfcommSocket = nullptr;
}
if (mRunnable) {
BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true));
mRunnable->SetReply(reply);
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
}
mRunnable = nullptr;
}
// Cache device address since we can't get socket address when a remote
// device disconnect with us.
mSocket->GetAddress(mConnectedDeviceAddress);
OnConnect(EmptyString());
}
void
BluetoothOppManager::OnConnectError(BluetoothSocket* aSocket)
BluetoothOppManager::OnSocketConnectError(BluetoothSocket* aSocket)
{
if (mRunnable) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING("OnConnectError:no runnable"));
mRunnable = nullptr;
}
mSocket = nullptr;
mRfcommSocket = nullptr;
mL2capSocket = nullptr;
Listen();
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
}
void
BluetoothOppManager::OnDisconnect(BluetoothSocket* aSocket)
BluetoothOppManager::OnSocketDisconnect(BluetoothSocket* aSocket)
{
MOZ_ASSERT(aSocket);
@ -1426,8 +1416,7 @@ BluetoothOppManager::OnDisconnect(BluetoothSocket* aSocket)
mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
mSuccessFlag = false;
mSocket = nullptr;
Listen();
OnDisconnect(EmptyString());
}
void
@ -1437,7 +1426,6 @@ BluetoothOppManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(mRunnable);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
@ -1447,22 +1435,14 @@ BluetoothOppManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
mNeedsUpdatingSdpRecords = false;
bs->UpdateSdpRecords(aDeviceAddress, this);
} else {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
}
return;
}
if (!mSocket->Connect(NS_ConvertUTF16toUTF8(aDeviceAddress), aChannel)) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING("SocketConnectionError"));
mRunnable = nullptr;
mSocket = nullptr;
Listen();
OnConnect(NS_LITERAL_STRING("SocketConnectionError"));
}
}
@ -1471,7 +1451,6 @@ 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);
@ -1480,11 +1459,7 @@ BluetoothOppManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
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();
OnConnect(NS_LITERAL_STRING(ERR_SERVICE_CHANNEL_NOT_FOUND));
}
}
@ -1502,3 +1477,41 @@ BluetoothOppManager::AcquireSdcardMountLock()
NS_ENSURE_SUCCESS(rv, false);
return true;
}
void
BluetoothOppManager::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aErrorStr.IsEmpty()) {
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.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnConnect(aErrorStr);
mController = nullptr;
}
void
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.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->OnDisconnect(aErrorStr);
mController = nullptr;
}

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

@ -45,20 +45,6 @@ public:
void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
/*
* If an application wants to send a file, first, it needs to
* call Connect() to create a valid RFCOMM connection. After
* that, call SendFile()/StopSendingFile() to control file-sharing
* process. During the file transfering process, the application
* will receive several system messages which contain the processed
* percentage of file. At the end, the application will get another
* system message indicating that the process is complete, then it can
* either call Disconnect() to close RFCOMM connection or start another
* file-sending thread via calling SendFile() again.
*/
void Connect(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
bool Listen();
bool SendFile(const nsAString& aDeviceAddress, BlobParent* aBlob);
@ -76,14 +62,15 @@ public:
bool ExtractBlobHeaders();
void CheckPutFinal(uint32_t aNumRead);
// Implement interface BluetoothSocketObserver
// The following functions are inherited from BluetoothSocketObserver
void ReceiveSocketData(
BluetoothSocket* aSocket,
nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
// The following functions are inherited from BluetoothProfileManagerBase
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
@ -91,6 +78,23 @@ public:
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
/*
* If an application wants to send a file, first, it needs to
* call Connect() to create a valid RFCOMM connection. After
* that, call SendFile()/StopSendingFile() to control file-sharing
* process. During the file transfering process, the application
* will receive several system messages which contain the processed
* percentage of file. At the end, the application will get another
* system message indicating that the process is complete, then it can
* either call Disconnect() to close RFCOMM connection or start another
* file-sending thread via calling SendFile() again.
*/
virtual void Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void Disconnect(BluetoothProfileController* aController) MOZ_OVERRIDE;
virtual void OnConnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
virtual void OnDisconnect(const nsAString& aErrorStr) MOZ_OVERRIDE;
private:
BluetoothOppManager();
bool Init();
@ -211,6 +215,7 @@ private:
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsIVolumeMountLock> mMountLock;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
BluetoothProfileController* mController;
nsRefPtr<DeviceStorageFile> mDsFile;
// If a connection has been established, mSocket will be the socket

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

@ -0,0 +1,221 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothA2dpManager.h"
#include "BluetoothHfpManager.h"
#include "BluetoothHidManager.h"
#include "BluetoothOppManager.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
USING_BLUETOOTH_NAMESPACE
BluetoothProfileController::BluetoothProfileController(
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
BluetoothProfileControllerCallback aCallback)
: mDeviceAddress(aDeviceAddress)
, mRunnable(aRunnable)
, mCallback(aCallback)
{
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(aCallback);
mProfilesIndex = -1;
mProfiles.Clear();
}
BluetoothProfileController::~BluetoothProfileController()
{
mProfiles.Clear();
mRunnable = nullptr;
mCallback = nullptr;
}
bool
BluetoothProfileController::AddProfileWithServiceClass(
BluetoothServiceClass aClass)
{
BluetoothProfileManagerBase* profile;
switch (aClass) {
case BluetoothServiceClass::HANDSFREE:
case BluetoothServiceClass::HEADSET:
profile = BluetoothHfpManager::Get();
break;
case BluetoothServiceClass::A2DP:
profile = BluetoothA2dpManager::Get();
break;
case BluetoothServiceClass::OBJECT_PUSH:
profile = BluetoothOppManager::Get();
break;
case BluetoothServiceClass::HID:
profile = BluetoothHidManager::Get();
break;
default:
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
mCallback();
return false;
}
return AddProfile(profile);
}
bool
BluetoothProfileController::AddProfile(BluetoothProfileManagerBase* aProfile,
bool aCheckConnected)
{
if (!aProfile) {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
mCallback();
return false;
}
if (aCheckConnected && !aProfile->IsConnected()) {
return false;
}
mProfiles.AppendElement(aProfile);
return true;
}
void
BluetoothProfileController::Connect(BluetoothServiceClass aClass)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(AddProfileWithServiceClass(aClass));
ConnectNext();
}
void
BluetoothProfileController::Connect(uint32_t aCod)
{
MOZ_ASSERT(NS_IsMainThread());
// Put multiple profiles into array and connect to all of them sequencely
bool hasAudio = HAS_AUDIO(aCod);
bool hasObjectTransfer = HAS_OBJECT_TRANSFER(aCod);
bool hasRendering = HAS_RENDERING(aCod);
bool isPeripheral = IS_PERIPHERAL(aCod);
NS_ENSURE_TRUE_VOID(hasAudio || hasObjectTransfer ||
hasRendering || isPeripheral);
mCod = aCod;
/**
* Connect to HFP/HSP first. Then, connect A2DP if Rendering bit is set.
* It's almost impossible to send file to a remote device which is an Audio
* device or a Rendering device, so we won't connect OPP in that case.
*/
BluetoothProfileManagerBase* profile;
if (hasAudio) {
AddProfile(BluetoothHfpManager::Get());
}
if (hasRendering) {
AddProfile(BluetoothA2dpManager::Get());
}
if (hasObjectTransfer && !hasAudio && !hasRendering) {
AddProfile(BluetoothOppManager::Get());
}
if (isPeripheral) {
AddProfile(BluetoothHidManager::Get());
}
ConnectNext();
}
void
BluetoothProfileController::ConnectNext()
{
MOZ_ASSERT(NS_IsMainThread());
if (++mProfilesIndex < mProfiles.Length()) {
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
mProfiles[mProfilesIndex]->Connect(mDeviceAddress, this);
return;
}
MOZ_ASSERT(mRunnable && mCallback);
// The action has been completed, so the dom request is replied and then
// the callback is invoked
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
mCallback();
}
void
BluetoothProfileController::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aErrorStr.IsEmpty()) {
BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
}
ConnectNext();
}
void
BluetoothProfileController::Disconnect(BluetoothServiceClass aClass)
{
MOZ_ASSERT(NS_IsMainThread());
if (aClass != BluetoothServiceClass::UNKNOWN) {
NS_ENSURE_TRUE_VOID(AddProfileWithServiceClass(aClass));
DisconnectNext();
return;
}
// Put all connected profiles into array and disconnect all of them
AddProfile(BluetoothHidManager::Get(), true);
AddProfile(BluetoothOppManager::Get(), true);
AddProfile(BluetoothA2dpManager::Get(), true);
AddProfile(BluetoothHfpManager::Get(), true);
DisconnectNext();
}
void
BluetoothProfileController::DisconnectNext()
{
MOZ_ASSERT(NS_IsMainThread());
if (++mProfilesIndex < mProfiles.Length()) {
mProfiles[mProfilesIndex]->Disconnect(this);
return;
}
MOZ_ASSERT(mRunnable && mCallback);
// The action has been completed, so the dom request is replied and then
// the callback is invoked
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
mCallback();
}
void
BluetoothProfileController::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
if (!aErrorStr.IsEmpty()) {
BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
}
DisconnectNext();
}

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

@ -0,0 +1,104 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothprofilecontroller_h__
#define mozilla_dom_bluetooth_bluetoothprofilecontroller_h__
#include "BluetoothUuid.h"
#include "nsAutoPtr.h"
BEGIN_BLUETOOTH_NAMESPACE
/*
* Class of Device(CoD): 32-bit unsigned integer
*
* 31 24 23 13 12 8 7 2 1 0
* | | Major | Major | Minor | |
* | | service | device | device | |
* | | class | class | class | |
* | |<- 11 ->|<- 5 ->|<- 6 ->| |
*
* https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband
*/
// Bit 23 ~ Bit 13: Major service class
#define GET_MAJOR_SERVICE_CLASS(cod) ((cod & 0xffe000) >> 13)
// Bit 12 ~ Bit 8: Major device class
#define GET_MAJOR_DEVICE_CLASS(cod) ((cod & 0x1f00) >> 8)
// Bit 7 ~ Bit 2: Minor device class
#define GET_MINOR_DEVICE_CLASS(cod) ((cod & 0xfc) >> 2)
// Bit 21: Major service class = 0x100, Audio
#define HAS_AUDIO(cod) (cod & 0x200000)
// Bit 20: Major service class = 0x80, Object Transfer
#define HAS_OBJECT_TRANSFER(cod) (cod & 0x100000)
// Bit 18: Major service class = 0x20, Rendering
#define HAS_RENDERING(cod) (cod & 0x40000)
// Major device class = 0xA, Peripheral
#define IS_PERIPHERAL(cod) (GET_MAJOR_DEVICE_CLASS(cod) == 0xa)
// Major device class = 0x4, Audio/Video
// Minor device class = 0x1, Wearable Headset device
#define IS_HEADSET(cod) ((GET_MAJOR_SERVICE_CLASS(cod) == 0x4) && \
(GET_MINOR_DEVICE_CLASS(cod) == 0x1))
class BluetoothProfileManagerBase;
class BluetoothReplyRunnable;
typedef void (*BluetoothProfileControllerCallback)();
class BluetoothProfileController
{
public:
BluetoothProfileController(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
BluetoothProfileControllerCallback aCallback);
~BluetoothProfileController();
// Connect to a specific service UUID.
void Connect(BluetoothServiceClass aClass);
// Based on the CoD, connect to multiple profiles sequencely.
void Connect(uint32_t aCod);
/**
* If aClass is assigned with specific service class, disconnect its
* corresponding profile. Otherwise, disconnect all profiles connected to the
* remote device.
*/
void Disconnect(BluetoothServiceClass aClass = BluetoothServiceClass::UNKNOWN);
void OnConnect(const nsAString& aErrorStr);
void OnDisconnect(const nsAString& aErrorStr);
uint32_t GetCod()
{
return mCod;
}
private:
void ConnectNext();
void DisconnectNext();
bool AddProfile(BluetoothProfileManagerBase* aProfile,
bool aCheckConnected = false);
bool AddProfileWithServiceClass(BluetoothServiceClass aClass);
int8_t mProfilesIndex;
nsTArray<BluetoothProfileManagerBase*> mProfiles;
uint32_t mCod;
nsString mDeviceAddress;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
BluetoothProfileControllerCallback mCallback;
};
END_BLUETOOTH_NAMESPACE
#endif

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

@ -13,14 +13,17 @@
* These error messages would be sent to Gaia as an argument of onError event.
*/
#define ERR_ALREADY_CONNECTED "AlreadyConnectedError"
#define ERR_ALREADY_DISCONNECTED "AlreadyDisconnectedError"
#define ERR_NO_AVAILABLE_RESOURCE "NoAvailableResourceError"
#define ERR_REACHED_CONNECTION_LIMIT "ReachedConnectionLimitError"
#define ERR_SERVICE_CHANNEL_NOT_FOUND "DeviceChannelRetrievalError"
#define ERR_UNKNOWN_PROFILE "UnknownProfileError"
#include "BluetoothCommon.h"
#include "nsIObserver.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothProfileController;
class BluetoothProfileManagerBase : public nsIObserver
{
@ -29,8 +32,35 @@ public:
const nsAString& aServiceUuid,
int aChannel) = 0;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) = 0;
/**
* Returns the address of the connected device.
*/
virtual void GetAddress(nsAString& aDeviceAddress) = 0;
/**
* Returns true if the profile is connected.
*/
virtual bool IsConnected() = 0;
/**
* Connect to a specific remote device. When it has been done, the
* callback "OnConnect" will be invoked.
*/
virtual void Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController) = 0;
/**
* Close the socket and then invoke the callback "OnDisconnect".
*/
virtual void Disconnect(BluetoothProfileController* aController) = 0;
/**
* If it establishes/releases a connection successfully, the error string
* will be empty. Otherwise, the error string shows the failure reason.
*/
virtual void OnConnect(const nsAString& aErrorStr) = 0;
virtual void OnDisconnect(const nsAString& aErrorStr) = 0;
};
END_BLUETOOTH_NAMESPACE

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

@ -9,7 +9,9 @@
#include "BluetoothService.h"
#include "BluetoothCommon.h"
#include "BluetoothA2dpManager.h"
#include "BluetoothHfpManager.h"
#include "BluetoothHidManager.h"
#include "BluetoothManager.h"
#include "BluetoothOppManager.h"
#include "BluetoothParent.h"
@ -460,11 +462,30 @@ BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
}
if (!aStart) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Disconnect();
BluetoothProfileManagerBase* profile;
profile = BluetoothHfpManager::Get();
NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE);
if (profile->IsConnected()) {
profile->Disconnect(nullptr);
}
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->Disconnect();
profile = BluetoothOppManager::Get();
NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE);
if (profile->IsConnected()) {
profile->Disconnect(nullptr);
}
profile = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE);
if (profile->IsConnected()) {
profile->Disconnect(nullptr);
}
profile = BluetoothHidManager::Get();
NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE);
if (profile->IsConnected()) {
profile->Disconnect(nullptr);
}
}
if (!mBluetoothThread) {

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

@ -139,7 +139,7 @@ public:
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) = 0;
/**
@ -233,15 +233,15 @@ public:
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
Connect(const nsAString& aDeviceAddress,
uint16_t aProfileId,
Connect(const nsAString& aDeviceAddress, uint32_t aCod, uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
Disconnect(uint16_t aProfileId, BluetoothReplyRunnable* aRunnable) = 0;
Disconnect(const nsAString& aDeviceAddress, uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) = 0;
virtual bool
IsConnected(uint16_t aProfileId) = 0;
IsConnected(uint16_t aServiceUuid) = 0;
virtual void
SendFile(const nsAString& aDeviceAddress,
@ -292,8 +292,7 @@ public:
virtual nsresult
SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage,
BluetoothReplyRunnable* aRunnable) = 0;
const nsAString& aMessage) = 0;
bool
IsEnabled() const

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

@ -77,7 +77,7 @@ BluetoothSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnConnectSuccess(this);
mObserver->OnSocketConnectSuccess(this);
}
void
@ -85,7 +85,7 @@ BluetoothSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnConnectError(this);
mObserver->OnSocketConnectError(this);
}
void
@ -93,6 +93,6 @@ BluetoothSocket::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnDisconnect(this);
mObserver->OnSocketDisconnect(this);
}

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

@ -21,26 +21,26 @@ class BluetoothSocketObserver
public:
virtual void ReceiveSocketData(BluetoothSocket* aSocket,
nsAutoPtr<UnixSocketRawData>& aMessage) = 0;
/**
* A callback function which would be called when a socket connection
* is established successfully. To be more specific, this would be called
* when socket state changes from CONNECTING/LISTENING to CONNECTED.
*/
virtual void OnConnectSuccess(BluetoothSocket* aSocket) = 0;
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) = 0;
/**
* A callback function which would be called when BluetoothSocket::Connect()
* fails.
*/
virtual void OnConnectError(BluetoothSocket* aSocket) = 0;
virtual void OnSocketConnectError(BluetoothSocket* aSocket) = 0;
/**
* A callback function which would be called when a socket connection
* is dropped. To be more specific, this would be called when socket state
* changes from CONNECTED/LISTENING to DISCONNECTED.
*/
virtual void OnDisconnect(BluetoothSocket* aSocket) = 0;
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) = 0;
};

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

@ -61,13 +61,11 @@ TelephonyListener::EnumerateCallState(uint32_t aCallIndex,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference,
bool* aResult)
bool aIsConference)
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber,
aIsOutgoing, false);
*aResult = true;
return NS_OK;
}
@ -117,10 +115,10 @@ bool
BluetoothTelephonyListener::StartListening()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, false);
nsresult rv = provider->RegisterTelephonyMsg(mTelephonyListener);
nsresult rv = provider->RegisterListener(mTelephonyListener);
NS_ENSURE_SUCCESS(rv, false);
return true;
@ -130,10 +128,10 @@ bool
BluetoothTelephonyListener::StopListening()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, false);
nsresult rv = provider->UnregisterTelephonyMsg(mTelephonyListener);
nsresult rv = provider->UnregisterListener(mTelephonyListener);
return NS_FAILED(rv) ? false : true;
}

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

@ -37,7 +37,14 @@ BluetoothUuidHelper::GetBluetoothServiceClass(const nsAString& aUuidStr)
int32_t integer = uuid.ToInteger(&rv, 16);
NS_ENSURE_SUCCESS(rv, retValue);
switch (integer) {
return GetBluetoothServiceClass(integer);
}
BluetoothServiceClass
BluetoothUuidHelper::GetBluetoothServiceClass(uint16_t aProfileId)
{
BluetoothServiceClass retValue = BluetoothServiceClass::UNKNOWN;
switch (aProfileId) {
case BluetoothServiceClass::A2DP:
case BluetoothServiceClass::HANDSFREE:
case BluetoothServiceClass::HANDSFREE_AG:
@ -45,7 +52,7 @@ BluetoothUuidHelper::GetBluetoothServiceClass(const nsAString& aUuidStr)
case BluetoothServiceClass::HEADSET_AG:
case BluetoothServiceClass::HID:
case BluetoothServiceClass::OBJECT_PUSH:
retValue = (BluetoothServiceClass)integer;
retValue = (BluetoothServiceClass)aProfileId;
}
return retValue;
}

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

@ -53,6 +53,9 @@ public:
*/
static BluetoothServiceClass
GetBluetoothServiceClass(const nsAString& aUuidStr);
static BluetoothServiceClass
GetBluetoothServiceClass(uint16_t aProfileId);
};
// TODO/qdot: Move these back into gonk and make the service handler deal with

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

@ -388,13 +388,14 @@ BluetoothRequestParent::DoRequest(const PairedDevicePropertiesRequest& aRequest)
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const ConnectedDevicePropertiesRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TConnectedDevicePropertiesRequest);
nsresult rv =
mService->GetConnectedDevicePropertiesInternal(aRequest.profileId(),
mService->GetConnectedDevicePropertiesInternal(aRequest.serviceUuid(),
mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
@ -474,7 +475,8 @@ BluetoothRequestParent::DoRequest(const ConnectRequest& aRequest)
MOZ_ASSERT(mRequestType == Request::TConnectRequest);
mService->Connect(aRequest.address(),
aRequest.profileId(),
aRequest.cod(),
aRequest.serviceUuid(),
mReplyRunnable.get());
return true;
@ -486,7 +488,8 @@ BluetoothRequestParent::DoRequest(const DisconnectRequest& aRequest)
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TDisconnectRequest);
mService->Disconnect(aRequest.profileId(),
mService->Disconnect(aRequest.address(),
aRequest.serviceUuid(),
mReplyRunnable.get());
return true;

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

@ -104,10 +104,10 @@ BluetoothServiceChildProcess::GetDefaultAdapterPathInternal(
nsresult
BluetoothServiceChildProcess::GetConnectedDevicePropertiesInternal(
uint16_t aProfileId,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, ConnectedDevicePropertiesRequest(aProfileId));
SendRequest(aRunnable, ConnectedDevicePropertiesRequest(aServiceUuid));
return NS_OK;
}
nsresult
@ -253,20 +253,24 @@ BluetoothServiceChildProcess::SetPairingConfirmationInternal(
void
BluetoothServiceChildProcess::Connect(
const nsAString& aDeviceAddress,
const uint16_t aProfileId,
uint32_t aCod,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
ConnectRequest(nsString(aDeviceAddress),
aProfileId));
aCod,
aServiceUuid));
}
void
BluetoothServiceChildProcess::Disconnect(
const uint16_t aProfileId,
const nsAString& aDeviceAddress,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, DisconnectRequest(aProfileId));
SendRequest(aRunnable,
DisconnectRequest(nsString(aDeviceAddress), aServiceUuid));
}
void
@ -387,7 +391,7 @@ BluetoothServiceChildProcess::IsEnabledInternal()
}
bool
BluetoothServiceChildProcess::IsConnected(uint16_t aProfileId)
BluetoothServiceChildProcess::IsConnected(uint16_t aServiceUuid)
{
MOZ_CRASH("This should never be called!");
}
@ -401,8 +405,7 @@ BluetoothServiceChildProcess::SendSinkMessage(const nsAString& aDeviceAddresses,
nsresult
BluetoothServiceChildProcess::SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage,
BluetoothReplyRunnable* aRunnable)
const nsAString& aMessage)
{
MOZ_CRASH("This should never be called!");
}

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

@ -52,7 +52,7 @@ public:
MOZ_OVERRIDE;
virtual nsresult
GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
MOZ_OVERRIDE;
virtual nsresult
@ -113,15 +113,17 @@ public:
virtual void
Connect(const nsAString& aDeviceAddress,
const uint16_t aProfileId,
uint32_t aCod,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
Disconnect(const uint16_t aProfileId,
Disconnect(const nsAString& aDeviceAddress,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
IsConnected(uint16_t aProfileId) MOZ_OVERRIDE;
IsConnected(uint16_t aServiceUuid) MOZ_OVERRIDE;
virtual void
SendFile(const nsAString& aDeviceAddress,
@ -173,8 +175,7 @@ public:
virtual nsresult
SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
const nsAString& aMessage) MOZ_OVERRIDE;
protected:
BluetoothServiceChildProcess();

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

@ -82,20 +82,23 @@ struct PairedDevicePropertiesRequest
{
nsString[] addresses;
};
struct ConnectedDevicePropertiesRequest
{
uint16_t profileId;
uint16_t serviceUuid;
};
struct ConnectRequest
{
nsString address;
uint16_t profileId;
uint32_t cod;
uint16_t serviceUuid;
};
struct DisconnectRequest
{
uint16_t profileId;
nsString address;
uint16_t serviceUuid;
};
struct SendFileRequest

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

@ -22,6 +22,7 @@
#include "BluetoothHfpManager.h"
#include "BluetoothHidManager.h"
#include "BluetoothOppManager.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothUnixSocketConnector.h"
#include "BluetoothUtils.h"
@ -78,7 +79,6 @@ USING_BLUETOOTH_NAMESPACE
#define ERR_A2DP_IS_DISCONNECTED "A2dpIsDisconnected"
#define ERR_AVRCP_IS_DISCONNECTED "AvrcpIsDisconnected"
#define ERR_UNKNOWN_PROFILE "UnknownProfileError"
/**
* To not lock Bluetooth switch button on Settings UI because of any accident,
@ -179,6 +179,7 @@ static nsString sAdapterPath;
static Atomic<int32_t> sIsPairing(0);
static int sConnectedDeviceCount = 0;
static StaticAutoPtr<Monitor> sStopBluetoothMonitor;
StaticAutoPtr<BluetoothProfileController> sController;
typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
typedef bool (*FilterFunc)(const BluetoothValue&);
@ -414,22 +415,6 @@ UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
}
}
void
BluetoothDBusService::DisconnectAllAcls(const nsAString& aAdapterPath)
{
MOZ_ASSERT(!NS_IsMainThread());
DBusMessage* reply =
dbus_func_args(gThreadConnection->GetConnection(),
NS_ConvertUTF16toUTF8(aAdapterPath).get(),
DBUS_ADAPTER_IFACE, "DisconnectAllConnections",
DBUS_TYPE_INVALID);
if (reply) {
dbus_message_unref(reply);
}
}
class PrepareProfileManagersRunnable : public nsRunnable
{
public:
@ -512,53 +497,90 @@ GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
UnpackVoidMessage);
}
static void
GetIntCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
class ReplyErrorToProfileManager : public nsRunnable
{
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
UnpackIntMessage);
}
public:
ReplyErrorToProfileManager(BluetoothServiceClass aServiceClass,
bool aConnect,
const nsAString& aErrorString)
: mServiceClass(aServiceClass)
, mConnect(aConnect)
, mErrorString(aErrorString)
{
MOZ_ASSERT(!NS_IsMainThread());
}
nsresult Run()
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothProfileManagerBase* profile;
if (mServiceClass == BluetoothServiceClass::HID) {
profile = BluetoothHidManager::Get();
} else if (mServiceClass == BluetoothServiceClass::A2DP) {
profile = BluetoothA2dpManager::Get();
} else {
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
if (mConnect) {
profile->OnConnect(mErrorString);
} else {
profile->OnDisconnect(mErrorString);
}
return NS_OK;
}
private:
BluetoothServiceClass mServiceClass;
bool mConnect;
nsString mErrorString;
};
#ifdef DEBUG
static void
CheckForError(DBusMessage* aMsg, void *aParam, const nsAString& aError)
CheckDBusReply(DBusMessage* aMsg, void* aServiceClass, bool aConnect)
{
MOZ_ASSERT(!NS_IsMainThread());
NS_ENSURE_TRUE_VOID(aMsg);
BluetoothValue v;
nsAutoString replyError;
UnpackVoidMessage(aMsg, nullptr, v, replyError);
if (!v.get_bool()) {
BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
nsAutoPtr<BluetoothServiceClass> serviceClass(
static_cast<BluetoothServiceClass*>(aServiceClass));
if (!replyError.IsEmpty()) {
NS_DispatchToMainThread(
new ReplyErrorToProfileManager(*serviceClass, aConnect, replyError));
}
}
#endif
static void
InputConnectCallback(DBusMessage* aMsg, void* aParam)
{
CheckDBusReply(aMsg, aParam, true);
}
static void
InputDisconnectCallback(DBusMessage* aMsg, void* aParam)
{
#ifdef DEBUG
NS_NAMED_LITERAL_STRING(errorStr, "Failed to disconnect input device");
CheckForError(aMsg, aParam, errorStr);
#endif
CheckDBusReply(aMsg, aParam, false);
}
static void
SinkConnectCallback(DBusMessage* aMsg, void* aParam)
{
#ifdef DEBUG
NS_NAMED_LITERAL_STRING(errorStr, "Failed to connect sink");
CheckForError(aMsg, aParam, errorStr);
#endif
CheckDBusReply(aMsg, aParam, true);
}
static void
SinkDisconnectCallback(DBusMessage* aMsg, void* aParam)
{
#ifdef DEBUG
NS_NAMED_LITERAL_STRING(errorStr, "Failed to disconnect sink");
CheckForError(aMsg, aParam, errorStr);
#endif
CheckDBusReply(aMsg, aParam, false);
}
static bool
@ -1950,38 +1972,55 @@ BluetoothDBusService::SendDiscoveryMessage(const char* aMessageName,
nsresult
BluetoothDBusService::SendInputMessage(const nsAString& aDeviceAddress,
const nsAString& aMessage,
BluetoothReplyRunnable* aRunnable)
const nsAString& aMessage)
{
DBusCallback callback;
if (aMessage.EqualsLiteral("Connect")) {
callback = InputConnectCallback;
} else if (aMessage.EqualsLiteral("Disconnect")) {
callback = InputDisconnectCallback;
} else {
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
nsString objectPath = GetObjectPathFromAddress(sAdapterPath, aDeviceAddress);
return SendAsyncDBusMessage(objectPath, DBUS_INPUT_IFACE, aMessage, callback);
}
nsresult
BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
const char* aInterface,
const nsAString& aMessage,
DBusCallback aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mConnection);
MOZ_ASSERT(aMessage.EqualsLiteral("Connect") ||
aMessage.EqualsLiteral("Disconnect"));
MOZ_ASSERT(IsEnabled());
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!aObjectPath.IsEmpty());
MOZ_ASSERT(aInterface);
NS_ENSURE_TRUE(IsReady(), NS_ERROR_FAILURE);
DBusCallback callback;
if (aMessage.EqualsLiteral("Connect")) {
callback = GetVoidCallback;
} else if (aMessage.EqualsLiteral("Disconnect")) {
callback = InputDisconnectCallback;
nsAutoPtr<BluetoothServiceClass> serviceClass(new BluetoothServiceClass());
if (!strcmp(aInterface, DBUS_SINK_IFACE)) {
*serviceClass = BluetoothServiceClass::A2DP;
} else if (!strcmp(aInterface, DBUS_INPUT_IFACE)) {
*serviceClass = BluetoothServiceClass::HID;
} else {
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
nsString objectPath = GetObjectPathFromAddress(sAdapterPath, aDeviceAddress);
bool ret = dbus_func_args_async(mConnection,
-1,
callback,
static_cast<void*>(runnable.get()),
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_INPUT_IFACE,
aCallback,
static_cast<void*>(serviceClass.forget()),
NS_ConvertUTF16toUTF8(aObjectPath).get(),
aInterface,
NS_ConvertUTF16toUTF8(aMessage).get(),
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(ret, NS_ERROR_FAILURE);
runnable.forget();
return NS_OK;
}
@ -1989,32 +2028,18 @@ nsresult
BluetoothDBusService::SendSinkMessage(const nsAString& aDeviceAddress,
const nsAString& aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mConnection);
MOZ_ASSERT(IsEnabled());
DBusCallback callback;
if (aMessage.EqualsLiteral("Connect")) {
callback = SinkConnectCallback;
} else if (aMessage.EqualsLiteral("Disconnect")) {
callback = SinkDisconnectCallback;
} else {
BT_WARNING("Unknown sink message");
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
nsString objectPath = GetObjectPathFromAddress(sAdapterPath, aDeviceAddress);
bool ret = dbus_func_args_async(mConnection,
-1,
callback,
nullptr,
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_SINK_IFACE,
NS_ConvertUTF16toUTF8(aMessage).get(),
DBUS_TYPE_INVALID);
NS_ENSURE_TRUE(ret, NS_ERROR_FAILURE);
return NS_OK;
return SendAsyncDBusMessage(objectPath, DBUS_SINK_IFACE, aMessage, callback);
}
nsresult
@ -2166,7 +2191,7 @@ private:
};
nsresult
BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -2181,12 +2206,12 @@ BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
nsTArray<nsString> deviceAddresses;
BluetoothProfileManagerBase* profile;
if (aProfileId == BluetoothServiceClass::HANDSFREE ||
aProfileId == BluetoothServiceClass::HEADSET) {
if (aServiceUuid == BluetoothServiceClass::HANDSFREE ||
aServiceUuid == BluetoothServiceClass::HEADSET) {
profile = BluetoothHfpManager::Get();
} else if (aProfileId == BluetoothServiceClass::HID) {
} else if (aServiceUuid == BluetoothServiceClass::HID) {
profile = BluetoothHidManager::Get();
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
} else if (aServiceUuid == BluetoothServiceClass::OBJECT_PUSH) {
profile = BluetoothOppManager::Get();
} else {
DispatchBluetoothReply(aRunnable, values,
@ -2589,70 +2614,79 @@ BluetoothDBusService::SetPairingConfirmationInternal(
return result;
}
static void
DestroyBluetoothProfileController()
{
sController = nullptr;
}
void
BluetoothDBusService::Connect(const nsAString& aDeviceAddress,
const uint16_t aProfileId,
uint32_t aCod,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
if (aProfileId == BluetoothServiceClass::HANDSFREE) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Connect(aDeviceAddress, true, aRunnable);
} else if (aProfileId == BluetoothServiceClass::HEADSET) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Connect(aDeviceAddress, false, aRunnable);
} else if (aProfileId == BluetoothServiceClass::HID) {
BluetoothHidManager* hid = BluetoothHidManager::Get();
hid->Connect(aDeviceAddress, aRunnable);
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->Connect(aDeviceAddress, aRunnable);
} else {
BluetoothServiceClass serviceClass =
BluetoothUuidHelper::GetBluetoothServiceClass(aServiceUuid);
if (sController) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
sController =
new BluetoothProfileController(aDeviceAddress, aRunnable,
DestroyBluetoothProfileController);
if (aServiceUuid) {
sController->Connect(serviceClass);
} else {
sController->Connect(aCod);
}
}
void
BluetoothDBusService::Disconnect(const uint16_t aProfileId,
BluetoothDBusService::Disconnect(const nsAString& aDeviceAddress,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
if (aProfileId == BluetoothServiceClass::HANDSFREE ||
aProfileId == BluetoothServiceClass::HEADSET) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Disconnect();
} else if (aProfileId == BluetoothServiceClass::HID) {
BluetoothHidManager* hid = BluetoothHidManager::Get();
hid->Disconnect();
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->Disconnect();
} else {
BT_WARNING(ERR_UNKNOWN_PROFILE);
BluetoothServiceClass serviceClass =
BluetoothUuidHelper::GetBluetoothServiceClass(aServiceUuid);
if (sController) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
// Currently, just fire success because Disconnect() doesn't fail,
// but we still make aRunnable pass into this function for future
// once Disconnect will fail.
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
sController =
new BluetoothProfileController(aDeviceAddress, aRunnable,
DestroyBluetoothProfileController);
if (aServiceUuid) {
sController->Disconnect(serviceClass);
} else {
sController->Disconnect();
}
}
bool
BluetoothDBusService::IsConnected(const uint16_t aProfileId)
BluetoothDBusService::IsConnected(const uint16_t aServiceUuid)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothProfileManagerBase* profile;
if (aProfileId == BluetoothServiceClass::HANDSFREE ||
aProfileId == BluetoothServiceClass::HEADSET) {
if (aServiceUuid == BluetoothServiceClass::HANDSFREE ||
aServiceUuid == BluetoothServiceClass::HEADSET) {
profile = BluetoothHfpManager::Get();
} else if (aProfileId == BluetoothServiceClass::HID) {
} else if (aServiceUuid == BluetoothServiceClass::HID) {
profile = BluetoothHidManager::Get();
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
} else if (aServiceUuid == BluetoothServiceClass::OBJECT_PUSH) {
profile = BluetoothOppManager::Get();
} else {
NS_WARNING(ERR_UNKNOWN_PROFILE);
@ -2950,7 +2984,7 @@ BluetoothDBusService::ConnectSco(BluetoothReplyRunnable* aRunnable)
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
NS_ENSURE_TRUE_VOID(hfp);
if(!hfp->ConnectSco(aRunnable)) {
if (!hfp->ConnectSco(aRunnable)) {
NS_NAMED_LITERAL_STRING(replyError,
"SCO socket exists or HFP is not connected");
DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
@ -3186,10 +3220,14 @@ BluetoothDBusService::SendPlayStatus(int64_t aDuration,
static void
ControlCallback(DBusMessage* aMsg, void* aParam)
{
#ifdef DEBUG
NS_NAMED_LITERAL_STRING(errorStr, "Failed to update playstatus");
CheckForError(aMsg, aParam, errorStr);
#endif
NS_ENSURE_TRUE_VOID(aMsg);
BluetoothValue v;
nsAutoString replyError;
UnpackVoidMessage(aMsg, nullptr, v, replyError);
if (!v.get_bool()) {
BT_WARNING(NS_ConvertUTF16toUTF8(replyError).get());
}
}
void

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

@ -36,7 +36,7 @@ public:
virtual nsresult GetDefaultAdapterPathInternal(
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult GetPairedDevicePropertiesInternal(
@ -102,14 +102,16 @@ public:
virtual void
Connect(const nsAString& aDeviceAddress,
const uint16_t aProfileId,
BluetoothReplyRunnable* aRunnable);
uint32_t aCod,
uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
IsConnected(uint16_t aProfileId) MOZ_OVERRIDE;
IsConnected(uint16_t aServiceUuid) MOZ_OVERRIDE;
virtual void
Disconnect(const uint16_t aProfileId, BluetoothReplyRunnable* aRunnable);
Disconnect(const nsAString& aDeviceAddress, uint16_t aServiceUuid,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual void
SendFile(const nsAString& aDeviceAddress,
@ -160,8 +162,8 @@ public:
virtual nsresult
SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
const nsAString& aMessage) MOZ_OVERRIDE;
protected:
BluetoothDBusService();
~BluetoothDBusService();
@ -198,7 +200,10 @@ private:
void UpdateNotification(ControlEventId aEventId, uint64_t aData);
void DisconnectAllAcls(const nsAString& aAdapterPath);
nsresult SendAsyncDBusMessage(const nsAString& aObjectPath,
const char* aInterface,
const nsAString& aMessage,
void (*aCallback)(DBusMessage*, void*));
};
END_BLUETOOTH_NAMESPACE

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

@ -44,6 +44,7 @@ if CONFIG['MOZ_B2G_BT']:
'ObexBase.cpp',
'BluetoothUuid.cpp',
'BluetoothSocket.cpp',
'BluetoothProfileController.cpp'
]
if CONFIG['MOZ_B2G_RIL']:

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

@ -40,7 +40,6 @@ DOM_SRCDIRS = \
ifdef MOZ_B2G_RIL
DOM_SRCDIRS += \
dom/system/gonk \
dom/telephony \
dom/wifi \
dom/icc/src \
$(NULL)

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

@ -96,6 +96,7 @@
#include "mozilla/dom/indexedDB/PIndexedDBChild.h"
#include "mozilla/dom/mobilemessage/SmsChild.h"
#include "mozilla/dom/telephony/TelephonyChild.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
#include "mozilla/dom/bluetooth/PBluetoothChild.h"
#include "mozilla/dom/PFMRadioChild.h"
@ -126,6 +127,7 @@ using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::ipc;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::indexedDB;
using namespace mozilla::dom::telephony;
using namespace mozilla::hal_sandbox;
using namespace mozilla::ipc;
using namespace mozilla::layers;
@ -919,6 +921,19 @@ ContentChild::DeallocPSmsChild(PSmsChild* aSms)
return true;
}
PTelephonyChild*
ContentChild::AllocPTelephonyChild()
{
MOZ_CRASH("No one should be allocating PTelephonyChild actors");
}
bool
ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor)
{
delete aActor;
return true;
}
PStorageChild*
ContentChild::AllocPStorageChild()
{

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

@ -152,6 +152,9 @@ public:
virtual PSmsChild* AllocPSmsChild();
virtual bool DeallocPSmsChild(PSmsChild*);
virtual PTelephonyChild* AllocPTelephonyChild();
virtual bool DeallocPTelephonyChild(PTelephonyChild*);
virtual PStorageChild* AllocPStorageChild();
virtual bool DeallocPStorageChild(PStorageChild* aActor);

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

@ -34,6 +34,7 @@
#include "mozilla/dom/bluetooth/PBluetoothParent.h"
#include "mozilla/dom/PFMRadioParent.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
#include "mozilla/dom/telephony/TelephonyParent.h"
#include "SmsParent.h"
#include "mozilla/Hal.h"
#include "mozilla/hal_sandbox/PHalParent.h"
@ -147,6 +148,7 @@ using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::indexedDB;
using namespace mozilla::dom::power;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::telephony;
using namespace mozilla::hal;
using namespace mozilla::idl;
using namespace mozilla::ipc;
@ -2244,6 +2246,25 @@ ContentParent::DeallocPSmsParent(PSmsParent* aSms)
return true;
}
PTelephonyParent*
ContentParent::AllocPTelephonyParent()
{
if (!AssertAppProcessPermission(this, "telephony")) {
return nullptr;
}
TelephonyParent* actor = new TelephonyParent();
NS_ADDREF(actor);
return actor;
}
bool
ContentParent::DeallocPTelephonyParent(PTelephonyParent* aActor)
{
static_cast<TelephonyParent*>(aActor)->Release();
return true;
}
PStorageParent*
ContentParent::AllocPStorageParent()
{

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

@ -321,6 +321,9 @@ private:
virtual PSmsParent* AllocPSmsParent();
virtual bool DeallocPSmsParent(PSmsParent*);
virtual PTelephonyParent* AllocPTelephonyParent();
virtual bool DeallocPTelephonyParent(PTelephonyParent*);
virtual PStorageParent* AllocPStorageParent();
virtual bool DeallocPStorageParent(PStorageParent* aActor);

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

@ -20,6 +20,7 @@ include protocol PNecko;
include protocol PSms;
include protocol PSpeechSynthesis;
include protocol PStorage;
include protocol PTelephony;
include protocol PTestShell;
include protocol PJavaScript;
include DOMTypes;
@ -197,6 +198,7 @@ rpc protocol PContent
manages PSms;
manages PSpeechSynthesis;
manages PStorage;
manages PTelephony;
manages PTestShell;
manages PJavaScript;
@ -353,6 +355,8 @@ parent:
PStorage();
PTelephony();
PBluetooth();
PFMRadio();

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

@ -25,6 +25,7 @@ XPIDL_SOURCES += [
if CONFIG['MOZ_B2G_RIL']:
XPIDL_SOURCES += [
'nsIRilMobileMessageDatabaseService.idl',
'nsIRilSmsService.idl',
]
XPIDL_MODULE = 'dom_mobilemessage'

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

@ -0,0 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISmsService.idl"
[scriptable, uuid(f216903c-bdf5-4988-b894-f62fd91df114)]
interface nsIRilSmsService : nsISmsService
{
void notifyMessageReceived(in jsval message);
};

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

@ -13,7 +13,7 @@ interface nsIMobileMessageCallback;
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
%}
[scriptable, builtinclass, uuid(0f3f75ec-00dd-11e3-87ac-0b1d5c79afdf)]
[scriptable, uuid(7ef8e361-9db6-46ed-badc-2901e1049e5d)]
interface nsISmsService : nsISupports
{
boolean hasSupport();
@ -26,7 +26,6 @@ interface nsISmsService : nsISupports
in boolean silent,
in nsIMobileMessageCallback request);
boolean isSilentNumber(in DOMString number);
void addSilentNumber(in DOMString number);
void removeSilentNumber(in DOMString number);
};

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

@ -26,12 +26,5 @@ LOCAL_INCLUDES = \
# subdirectory (and the ipc one).
LOCAL_INCLUDES += $(VPATH:%=-I%)
ifdef MOZ_B2G_RIL
LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/telephony \
-I$(topsrcdir)/dom/system/gonk \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk

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

@ -5,16 +5,18 @@
#include "SmsServicesFactory.h"
#include "nsXULAppAPI.h"
#include "SmsService.h"
#include "SmsIPCService.h"
#ifndef MOZ_B2G_RIL
#include "MobileMessageDatabaseService.h"
#include "MmsService.h"
#include "SmsService.h"
#endif
#include "nsServiceManagerUtils.h"
#define RIL_MMSSERVICE_CONTRACTID "@mozilla.org/mms/rilmmsservice;1"
#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1"
#define RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID \
"@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1"
#define RIL_SMSSERVICE_CONTRACTID "@mozilla.org/sms/rilsmsservice;1"
namespace mozilla {
namespace dom {
@ -28,7 +30,11 @@ SmsServicesFactory::CreateSmsService()
if (XRE_GetProcessType() == GeckoProcessType_Content) {
smsService = new SmsIPCService();
} else {
#ifdef MOZ_B2G_RIL
smsService = do_GetService(RIL_SMSSERVICE_CONTRACTID);
#else
smsService = new SmsService();
#endif
}
return smsService.forget();
@ -42,7 +48,8 @@ SmsServicesFactory::CreateMobileMessageDatabaseService()
mobileMessageDBService = new SmsIPCService();
} else {
#ifdef MOZ_B2G_RIL
mobileMessageDBService = do_GetService(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
mobileMessageDBService =
do_GetService(RIL_MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
#else
mobileMessageDBService = new MobileMessageDatabaseService();
#endif

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

@ -50,14 +50,6 @@ SmsService::Send(const nsAString& aNumber,
return NS_OK;
}
NS_IMETHODIMP
SmsService::IsSilentNumber(const nsAString& aNumber,
bool* aIsSilent)
{
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
SmsService::AddSilentNumber(const nsAString& aNumber)
{

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

@ -39,14 +39,6 @@ SmsService::Send(const nsAString& aNumber,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SmsService::IsSilentNumber(const nsAString& aNumber,
bool* aIsSilent)
{
NS_ERROR("We should not be here!");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SmsService::AddSilentNumber(const nsAString& aNumber)
{

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

@ -1,85 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SmsMessage.h"
#include "SmsService.h"
#include "jsapi.h"
#include "SmsSegmentInfo.h"
namespace mozilla {
namespace dom {
namespace mobilemessage {
NS_IMPL_ISUPPORTS1(SmsService, nsISmsService)
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!");
}
NS_IMETHODIMP
SmsService::HasSupport(bool* aHasSupport)
{
*aHasSupport = true;
return NS_OK;
}
NS_IMETHODIMP
SmsService::GetSegmentInfoForText(const nsAString& aText,
nsIMobileMessageCallback* aRequest)
{
NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
return mRadioInterface->GetSegmentInfoForText(aText, aRequest);
}
NS_IMETHODIMP
SmsService::Send(const nsAString& aNumber,
const nsAString& aMessage,
const bool aSilent,
nsIMobileMessageCallback* aRequest)
{
NS_ENSURE_TRUE(mRadioInterface, NS_ERROR_FAILURE);
return mRadioInterface->SendSMS(aNumber, aMessage, aSilent, aRequest);
}
NS_IMETHODIMP
SmsService::IsSilentNumber(const nsAString& aNumber,
bool* aIsSilent)
{
*aIsSilent = mSilentNumbers.Contains(aNumber);
return NS_OK;
}
NS_IMETHODIMP
SmsService::AddSilentNumber(const nsAString& aNumber)
{
if (mSilentNumbers.Contains(aNumber)) {
return NS_ERROR_UNEXPECTED;
}
NS_ENSURE_TRUE(mSilentNumbers.AppendElement(aNumber), NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP
SmsService::RemoveSilentNumber(const nsAString& aNumber)
{
if (!mSilentNumbers.Contains(aNumber)) {
return NS_ERROR_INVALID_ARG;
}
NS_ENSURE_TRUE(mSilentNumbers.RemoveElement(aNumber), NS_ERROR_FAILURE);
return NS_OK;
}
} // namespace mobilemessage
} // namespace dom
} // namespace mozilla

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

@ -1,35 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_mobilemessage_SmsService_h
#define mozilla_dom_mobilemessage_SmsService_h
#include "nsISmsService.h"
#include "nsCOMPtr.h"
#include "nsIRadioInterfaceLayer.h"
#include "nsTArray.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
namespace mobilemessage {
class SmsService : public nsISmsService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISMSSERVICE
SmsService();
protected:
// TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS
nsCOMPtr<nsIRadioInterface> mRadioInterface;
nsTArray<nsString> mSilentNumbers;
};
} // namespace mobilemessage
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_mobilemessage_SmsService_h

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,3 @@
# SmsService.js
component {46a9ed78-3574-40a1-9f12-ea179942d67f} SmsService.js
contract @mozilla.org/sms/rilsmsservice;1 {46a9ed78-3574-40a1-9f12-ea179942d67f}

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

@ -115,14 +115,6 @@ SmsIPCService::Send(const nsAString& aNumber,
aRequest);
}
NS_IMETHODIMP
SmsIPCService::IsSilentNumber(const nsAString& aNumber,
bool* aIsSilent)
{
NS_ERROR("We should not be here!");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
SmsIPCService::AddSilentNumber(const nsAString& aNumber)
{

4
dom/mobilemessage/src/ipc/SmsParent.cpp Normal file → Executable file
Просмотреть файл

@ -584,6 +584,8 @@ SmsRequestParent::SendReply(const MessageReply& aReply)
NS_IMETHODIMP
SmsRequestParent::NotifyMessageSent(nsISupports *aMessage)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMMozMmsMessage> mms = do_QueryInterface(aMessage);
if (mms) {
MmsMessage *msg = static_cast<MmsMessage*>(mms.get());
@ -613,6 +615,8 @@ SmsRequestParent::NotifySendMessageFailed(int32_t aError)
NS_IMETHODIMP
SmsRequestParent::NotifyMessageGot(nsISupports *aMessage)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMMozMmsMessage> mms = do_QueryInterface(aMessage);
if (mms) {
MmsMessage *msg = static_cast<MmsMessage*>(mms.get());

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

@ -36,6 +36,7 @@ else:
CPP_SOURCES += [
'MobileMessageDatabaseService.cpp',
'MmsService.cpp',
'SmsService.cpp',
]
EXPORTS.mozilla.dom += [
@ -60,7 +61,6 @@ CPP_SOURCES += [
'SmsMessage.cpp',
'SmsParent.cpp',
'SmsSegmentInfo.cpp',
'SmsService.cpp',
'SmsServicesFactory.cpp',
]
@ -70,6 +70,8 @@ if CONFIG['MOZ_B2G_RIL']:
'gonk/MmsService.manifest',
'gonk/MobileMessageDatabaseService.js',
'gonk/MobileMessageDatabaseService.manifest',
'gonk/SmsService.js',
'gonk/SmsService.manifest',
]
IPDL_SOURCES += [

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

@ -72,7 +72,8 @@ PARALLEL_DIRS += [
'camera',
'audiochannel',
'promise',
'wappush'
'wappush',
'telephony',
]
if CONFIG['OS_ARCH'] == 'WINNT':
@ -80,7 +81,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
if CONFIG['MOZ_B2G_RIL']:
PARALLEL_DIRS += [
'telephony',
'wifi',
'icc',
'cellbroadcast',

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

@ -17,7 +17,6 @@ include $(topsrcdir)/dom/dom-config.mk
LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/src/geolocation \
-I$(topsrcdir)/dom/telephony \
-I$(topsrcdir)/dom/wifi \
-I$(topsrcdir)/dom/bluetooth \
-I$(topsrcdir)/content/events/src \

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

@ -71,17 +71,13 @@ const RIL_IPC_MSG_NAMES = [
"RIL:IccInfoChanged",
"RIL:VoiceInfoChanged",
"RIL:DataInfoChanged",
"RIL:EnumerateCalls",
"RIL:GetAvailableNetworks",
"RIL:NetworkSelectionModeChanged",
"RIL:SelectNetwork",
"RIL:SelectNetworkAuto",
"RIL:CallStateChanged",
"RIL:EmergencyCbModeChanged",
"RIL:VoicemailNotification",
"RIL:VoicemailInfoChanged",
"RIL:CallError",
"RIL:SuppSvcNotification",
"RIL:CardLockResult",
"RIL:CardLockRetryCount",
"RIL:USSDReceived",
@ -108,11 +104,9 @@ const RIL_IPC_MSG_NAMES = [
"RIL:UpdateIccContact",
"RIL:SetRoamingPreference",
"RIL:GetRoamingPreference",
"RIL:CdmaCallWaiting",
"RIL:ExitEmergencyCbMode",
"RIL:SetVoicePrivacyMode",
"RIL:GetVoicePrivacyMode",
"RIL:ConferenceCallStateChanged",
"RIL:OtaStatusChanged"
];
@ -120,10 +114,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
function MobileIccCardLockResult(options) {
this.lockType = options.lockType;
this.enabled = options.enabled;
@ -449,7 +439,6 @@ RILContentHelper.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
Ci.nsICellBroadcastProvider,
Ci.nsIVoicemailProvider,
Ci.nsITelephonyProvider,
Ci.nsIIccProvider,
Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
@ -459,7 +448,6 @@ RILContentHelper.prototype = {
interfaces: [Ci.nsIMobileConnectionProvider,
Ci.nsICellBroadcastProvider,
Ci.nsIVoicemailProvider,
Ci.nsITelephonyProvider,
Ci.nsIIccProvider]}),
// An utility function to copy objects.
@ -1281,11 +1269,9 @@ RILContentHelper.prototype = {
},
_mobileConnectionListeners: null,
_telephonyListeners: null,
_cellBroadcastListeners: null,
_voicemailListeners: null,
_iccListeners: null,
_enumerateTelephonyCallbacks: null,
voicemailStatus: null,
@ -1347,24 +1333,6 @@ RILContentHelper.prototype = {
this.unregisterListener("_mobileConnectionListeners", listener);
},
registerTelephonyMsg: function registerTelephonyMsg(listener) {
debug("Registering for telephony-related messages");
this.registerListener("_telephonyListeners", listener);
cpmm.sendAsyncMessage("RIL:RegisterTelephonyMsg");
},
unregisterTelephonyMsg: function unregisteTelephonyMsg(listener) {
this.unregisterListener("_telephonyListeners", listener);
// We also need to make sure the listener is removed from
// _enumerateTelephonyCallbacks.
let index = this._enumerateTelephonyCallbacks.indexOf(listener);
if (index != -1) {
this._enumerateTelephonyCallbacks.splice(index, 1);
if (DEBUG) debug("Unregistered enumerateTelephony callback: " + listener);
}
},
registerVoicemailMsg: function registerVoicemailMsg(listener) {
debug("Registering for voicemail-related messages");
this.registerListener("_voicemailListeners", listener);
@ -1395,135 +1363,6 @@ RILContentHelper.prototype = {
this.unregisterListener("_iccListeners", listener);
},
enumerateCalls: function enumerateCalls(callback) {
debug("Requesting enumeration of calls for callback: " + callback);
// We need 'requestId' to meet the 'RILContentHelper <--> RadioInterfaceLayer'
// protocol.
let requestId = this._getRandomId();
cpmm.sendAsyncMessage("RIL:EnumerateCalls", {
clientId: 0,
data: {
requestId: requestId
}
});
if (!this._enumerateTelephonyCallbacks) {
this._enumerateTelephonyCallbacks = [];
}
this._enumerateTelephonyCallbacks.push(callback);
},
startTone: function startTone(dtmfChar) {
debug("Sending Tone for " + dtmfChar);
cpmm.sendAsyncMessage("RIL:StartTone", {
clientId: 0,
data: dtmfChar
});
},
stopTone: function stopTone() {
debug("Stopping Tone");
cpmm.sendAsyncMessage("RIL:StopTone", {clientId: 0});
},
dial: function dial(number) {
debug("Dialing " + number);
cpmm.sendAsyncMessage("RIL:Dial", {
clientId: 0,
data: number
});
},
dialEmergency: function dialEmergency(number) {
debug("Dialing emergency " + number);
cpmm.sendAsyncMessage("RIL:DialEmergency", {
clientId: 0,
data: number
});
},
hangUp: function hangUp(callIndex) {
debug("Hanging up call no. " + callIndex);
cpmm.sendAsyncMessage("RIL:HangUp", {
clientId: 0,
data: callIndex
});
},
answerCall: function answerCall(callIndex) {
cpmm.sendAsyncMessage("RIL:AnswerCall", {
clientId: 0,
data: callIndex
});
},
rejectCall: function rejectCall(callIndex) {
cpmm.sendAsyncMessage("RIL:RejectCall", {
clientId: 0,
data: callIndex
});
},
holdCall: function holdCall(callIndex) {
cpmm.sendAsyncMessage("RIL:HoldCall", {
clientId: 0,
data: callIndex
});
},
resumeCall: function resumeCall(callIndex) {
cpmm.sendAsyncMessage("RIL:ResumeCall", {
clientId: 0,
data: callIndex
});
},
conferenceCall: function conferenceCall() {
cpmm.sendAsyncMessage("RIL:ConferenceCall", {
clientId: 0
});
},
separateCall: function separateCall(callIndex) {
cpmm.sendAsyncMessage("RIL:SeparateCall", {
clientId: 0,
data: callIndex
});
},
holdConference: function holdConference() {
cpmm.sendAsyncMessage("RIL:HoldConference", {
clientId: 0
});
},
resumeConference: function resumeConference() {
cpmm.sendAsyncMessage("RIL:ResumeConference", {
clientId: 0
});
},
get microphoneMuted() {
return cpmm.sendSyncMessage("RIL:GetMicrophoneMuted", {clientId: 0})[0];
},
set microphoneMuted(value) {
cpmm.sendAsyncMessage("RIL:SetMicrophoneMuted", {
clientId: 0,
data: value
});
},
get speakerEnabled() {
return cpmm.sendSyncMessage("RIL:GetSpeakerEnabled", {clientId: 0})[0];
},
set speakerEnabled(value) {
cpmm.sendAsyncMessage("RIL:SetSpeakerEnabled", {
clientId: 0,
data: value
});
},
// nsIObserver
observe: function observe(subject, topic, data) {
@ -1620,9 +1459,6 @@ RILContentHelper.prototype = {
"notifyOtaStatusChanged",
[msg.json.data]);
break;
case "RIL:EnumerateCalls":
this.handleEnumerateCalls(msg.json.calls);
break;
case "RIL:GetAvailableNetworks":
this.handleGetAvailableNetworks(msg.json);
break;
@ -1637,35 +1473,6 @@ RILContentHelper.prototype = {
this.handleSelectNetwork(msg.json,
RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
break;
case "RIL:CallStateChanged": {
let data = msg.json.data;
this._deliverEvent("_telephonyListeners",
"callStateChanged",
[data.callIndex, data.state,
data.number, data.isActive,
data.isOutgoing, data.isEmergency,
data.isConference]);
break;
}
case "RIL:ConferenceCallStateChanged": {
let data = msg.json.data;
this._deliverEvent("_telephonyListeners",
"conferenceCallStateChanged",
[data]);
break;
}
case "RIL:CallError": {
let data = msg.json.data;
this._deliverEvent("_telephonyListeners",
"notifyError",
[data.callIndex, data.errorMsg]);
break;
}
case "RIL:SuppSvcNotification":
this._deliverEvent("_telephonyListeners",
"supplementaryServiceNotification",
[msg.json.callIndex, msg.json.notification]);
break;
case "RIL:VoicemailNotification":
this.handleVoicemailNotification(msg.json.data);
break;
@ -1786,11 +1593,6 @@ RILContentHelper.prototype = {
this.handleSimpleRequest(msg.json.requestId, msg.json.errorMsg,
msg.json.mode);
break;
case "RIL:CdmaCallWaiting":
this._deliverEvent("_telephonyListeners",
"notifyCdmaCallWaiting",
[msg.json.data]);
break;
case "RIL:ExitEmergencyCbMode":
this.handleExitEmergencyCbMode(msg.json);
break;
@ -1810,35 +1612,6 @@ 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;
try {
keepGoing =
callback.enumerateCallState(call.callIndex, call.state, call.number,
call.isActive, call.isOutgoing,
call.isEmergency, call.isConference);
} catch (e) {
debug("callback handler for 'enumerateCallState' threw an " +
" exception: " + e);
keepGoing = true;
}
if (!keepGoing) {
break;
}
}
callback.enumerateCallStateComplete();
},
handleSimpleRequest: function handleSimpleRequest(requestId, errorMsg, result) {
if (errorMsg) {
this.fireRequestError(requestId, errorMsg);
@ -2051,10 +1824,6 @@ RILContentHelper.prototype = {
}
},
_getRandomId: function _getRandomId() {
return gUUIDGenerator.generateUUID().toString();
},
_deliverEvent: function _deliverEvent(listenerType, name, args) {
let thisListeners = this[listenerType];
if (!thisListeners) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,330 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
"nsIMessageBroadcaster");
// Observer topics.
const kPrefenceChangedObserverTopic = "nsPref:changed";
const kSysMsgListenerReadyObserverTopic = "system-message-listener-ready";
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
// Preference keys.
const kPrefKeyRilDebuggingEnabled = "ril.debugging.enabled";
// Frame message names.
const kMsgNameChildProcessShutdown = "child-process-shutdown";
let DEBUG;
function debug(s) {
dump("RilMessageManager: " + s + "\n");
}
this.RilMessageManager = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
Ci.nsIObserver]),
topicRegistrationNames: {
cellbroadcast: "RIL:RegisterCellBroadcastMsg",
icc: "RIL:RegisterIccMsg",
mobileconnection: "RIL:RegisterMobileConnectionMsg",
voicemail: "RIL:RegisterVoicemailMsg",
},
/**
* this.callbacksByName[< A string message name>] = {
* topic: <A string topic>,
* callback: <A callback that accepts two parameters -- topic and msg>,
* }
*/
callbacksByName: {},
// Manage message targets in terms of topic. Only the authorized and
// registered contents can receive related messages.
targetsByTopic: {},
topics: [],
targetMessageQueue: [],
ready: false,
_init: function _init() {
this._updateDebugFlag();
Services.obs.addObserver(this, kPrefenceChangedObserverTopic, false);
Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false);
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
ppmm.addMessageListener(kMsgNameChildProcessShutdown, this);
let callback = this._registerMessageTarget.bind(this);
for (let topic in this.topicRegistrationNames) {
let name = this.topicRegistrationNames[topic];
this.registerMessageListeners(topic, [name], callback);
}
},
_shutdown: function _shutdown() {
if (!this.ready) {
Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
}
Services.obs.removeObserver(this, kPrefenceChangedObserverTopic);
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
for (let name in this.callbacksByName) {
ppmm.removeMessageListener(name, this);
}
this.callbacksByName = null;
ppmm.removeMessageListener(kMsgNameChildProcessShutdown, this);
ppmm = null;
this.targetsByTopic = null;
this.targetMessageQueue = null;
},
_registerMessageTarget: function _registerMessageTarget(topic, msg) {
let targets = this.targetsByTopic[topic];
if (!targets) {
targets = this.targetsByTopic[topic] = [];
let list = this.topics;
if (list.indexOf(topic) == -1) {
list.push(topic);
}
}
let target = msg.target;
if (targets.indexOf(target) != -1) {
if (DEBUG) debug("Already registered this target!");
return;
}
targets.push(target);
if (DEBUG) debug("Registered " + topic + " target: " + target);
},
_unregisterMessageTarget: function _unregisterMessageTarget(topic, target) {
if (topic == null) {
// Unregister the target for every topic when no topic is specified.
for (let type of this.topics) {
this._unregisterMessageTarget(type, target);
}
return;
}
// Unregister the target for a specified topic.
let targets = this.targetsByTopic[topic];
if (!targets) {
return;
}
let index = targets.indexOf(target);
if (index != -1) {
targets.splice(index, 1);
if (DEBUG) debug("Unregistered " + topic + " target: " + target);
}
},
_enqueueTargetMessage: function _enqueueTargetMessage(topic, name, options) {
let msg = { topic : topic,
name : name,
options : options };
// Remove previous queued message of same message name, only one message
// per message name is allowed in queue.
let messageQueue = this.targetMessageQueue;
for (let i = 0; i < messageQueue.length; i++) {
if (messageQueue[i].name === name) {
messageQueue.splice(i, 1);
break;
}
}
messageQueue.push(msg);
},
_sendTargetMessage: function _sendTargetMessage(topic, name, options) {
if (!this.ready) {
this._enqueueTargetMessage(topic, name, options);
return;
}
let targets = this.targetsByTopic[topic];
if (!targets) {
return;
}
for (let target of targets) {
target.sendAsyncMessage(name, options);
}
},
_resendQueuedTargetMessage: function _resendQueuedTargetMessage() {
// Here uses this._sendTargetMessage() to resend message, which will
// enqueue message if listener is not ready. So only resend after listener
// is ready, or it will cause infinate loop and hang the system.
// Dequeue and resend messages.
for (let msg of this.targetMessageQueue) {
this._sendTargetMessage(msg.topic, msg.name, msg.options);
}
this.targetMessageQueue = null;
},
_updateDebugFlag: function _updateDebugFlag() {
try {
DEBUG = RIL.DEBUG_RIL ||
Services.prefs.getBoolPref(kPrefKeyRilDebuggingEnabled);
} catch(e) {}
},
/**
* nsIMessageListener interface methods.
*/
receiveMessage: function receiveMessage(msg) {
if (DEBUG) {
debug("Received '" + msg.name + "' message from content process");
}
if (msg.name == kMsgNameChildProcessShutdown) {
// By the time we receive child-process-shutdown, the child process has
// already forgotten its permissions so we need to unregister the target
// for every permission.
this._unregisterMessageTarget(null, msg.target);
return;
}
let entry = this.callbacksByName[msg.name];
if (!entry) {
if (DEBUG) debug("Ignoring unknown message type: " + msg.name);
return null;
}
if (entry.topic && !msg.target.assertPermission(entry.topic)) {
if (DEBUG) {
debug("Message " + msg.name + " from a content process with no '" +
entry.topic + "' privileges.");
}
return null;
}
return entry.callback(entry.topic, msg);
},
/**
* nsIObserver interface methods.
*/
observe: function observe(subject, topic, data) {
switch (topic) {
case kSysMsgListenerReadyObserverTopic:
this.ready = true;
Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
this._resendQueuedTargetMessage();
break;
case kPrefenceChangedObserverTopic:
if (data === kPrefKeyRilDebuggingEnabled) {
this._updateDebugFlag();
}
break;
case kXpcomShutdownObserverTopic:
this._shutdown();
break;
}
},
/**
* Public methods.
*/
/**
* @param topic
* A string for the topic of the registrating names. Also the
* permission to listen messages of these names.
* @param names
* An array of string message names to listen.
* @param callback
* A callback that accepts two parameters -- topic and msg.
*/
registerMessageListeners: function registerMessageListeners(topic, names,
callback) {
for (let name of names) {
if (this.callbacksByName[name]) {
if (DEBUG) {
debug("Message name '" + name + "' was already registered. Ignored.");
}
continue;
}
this.callbacksByName[name] = { topic: topic, callback: callback };
ppmm.addMessageListener(name, this);
}
},
/**
* Remove all listening names with specified callback.
*
* @param callback
* The callback previously registered for messages.
*/
unregisterMessageListeners: function unregisterMessageListeners(callback) {
let remains = {};
for (let name in this.callbacksByName) {
let entry = this.callbacksByName[name];
if (entry.callback != callback) {
remains[name] = entry;
} else {
ppmm.removeMessageListener(name, this);
}
}
this.callbacksByName = remains;
},
sendMobileConnectionMessage: function sendMobileConnectionMessage(name,
clientId,
data) {
this._sendTargetMessage("mobileconnection", name, {
clientId: clientId,
data: data
});
},
sendVoicemailMessage: function sendVoicemailMessage(name, clientId, data) {
this._sendTargetMessage("voicemail", name, {
clientId: clientId,
data: data
});
},
sendCellBroadcastMessage: function sendCellBroadcastMessage(name, clientId,
data) {
this._sendTargetMessage("cellbroadcast", name, {
clientId: clientId,
data: data
});
},
sendIccMessage: function sendIccMessage(name, clientId, data) {
this._sendTargetMessage("icc", name, {
clientId: clientId,
data: data
});
}
};
RilMessageManager._init();
this.EXPORTED_SYMBOLS = ["RilMessageManager"];

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

@ -137,8 +137,7 @@ PostToRIL(JSContext *cx, unsigned argc, JS::Value *vp)
return false;
}
UnixSocketRawData* raw = new UnixSocketRawData(size);
memcpy(raw->mData, data, raw->mSize);
UnixSocketRawData* raw = new UnixSocketRawData(data, size);
nsRefPtr<SendRilSocketDataTask> task = new SendRilSocketDataTask(clientId, raw);
NS_DispatchToMainThread(task);

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

@ -74,6 +74,7 @@ EXTRA_COMPONENTS += [
]
EXTRA_JS_MODULES += [
'RilMessageManager.jsm',
'net_worker.js',
'ril_consts.js',
'ril_worker.js',

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

@ -6,7 +6,6 @@
interface nsIDOMMozIccInfo;
interface nsIDOMMozMobileConnectionInfo;
interface nsIMobileMessageCallback;
[scriptable, uuid(1e602d20-d066-4399-8997-daf36b3158ef)]
interface nsIRILDataCallInfo : nsISupports
@ -78,7 +77,13 @@ interface nsIRilContext : nsISupports
readonly attribute nsIDOMMozMobileConnectionInfo data;
};
[scriptable, uuid(a50d65aa-00da-11e3-b954-7bfb233d98fc)]
[scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
interface nsIRilSendWorkerMessageCallback : nsISupports
{
boolean handleResponse(in jsval response);
};
[scriptable, uuid(b1af7aad-6547-427c-a878-e2ebf98a14d6)]
interface nsIRadioInterface : nsISupports
{
readonly attribute nsIRilContext rilContext;
@ -95,16 +100,9 @@ interface nsIRadioInterface : nsISupports
void updateRILNetworkInterface();
/**
* SMS-related functionality.
*/
void getSegmentInfoForText(in DOMString text,
in nsIMobileMessageCallback request);
void sendSMS(in DOMString number,
in DOMString message,
in boolean silent,
in nsIMobileMessageCallback request);
void sendWorkerMessage(in DOMString type,
[optional] in jsval message,
[optional] in nsIRilSendWorkerMessageCallback callback);
};
[scriptable, uuid(44b03951-1444-4c03-bd37-0bcb3a01b56f)]

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

@ -11,6 +11,7 @@
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
using mozilla::ErrorResult;
/* static */
already_AddRefed<CallEvent>

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

@ -3,3 +3,5 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include $(topsrcdir)/dom/dom-config.mk
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk

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

@ -24,10 +24,9 @@
#include "TelephonyCall.h"
#include "TelephonyCallGroup.h"
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
using mozilla::ErrorResult;
namespace {
@ -51,6 +50,8 @@ public:
MOZ_ASSERT(mTelephony);
}
virtual ~Listener() {}
void
Disconnect()
{
@ -111,7 +112,7 @@ Telephony::Shutdown()
mListener->Disconnect();
if (mProvider) {
mProvider->UnregisterTelephonyMsg(mListener);
mProvider->UnregisterListener(mListener);
mProvider = nullptr;
}
@ -132,7 +133,7 @@ Telephony::Create(nsPIDOMWindow* aOwner, ErrorResult& aRv)
NS_ASSERTION(aOwner, "Null owner!");
nsCOMPtr<nsITelephonyProvider> ril =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
if (!ril) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
@ -165,7 +166,7 @@ Telephony::Create(nsPIDOMWindow* aOwner, ErrorResult& aRv)
return nullptr;
}
rv = ril->RegisterTelephonyMsg(telephony->mListener);
rv = ril->RegisterListener(telephony->mListener);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
@ -222,12 +223,7 @@ Telephony::DialInternal(bool isEmergency,
}
}
nsresult rv;
if (isEmergency) {
rv = mProvider->DialEmergency(aNumber);
} else {
rv = mProvider->Dial(aNumber);
}
nsresult rv = mProvider->Dial(aNumber, isEmergency);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
@ -591,7 +587,7 @@ NS_IMETHODIMP
Telephony::EnumerateCallState(uint32_t aCallIndex, uint16_t aCallState,
const nsAString& aNumber, bool aIsActive,
bool aIsOutgoing, bool aIsEmergency,
bool aIsConference, bool* aContinue)
bool aIsConference)
{
nsRefPtr<TelephonyCall> call;
@ -603,12 +599,10 @@ Telephony::EnumerateCallState(uint32_t aCallIndex, uint16_t aCallState,
call = aIsConference ? mGroup->GetCall(aCallIndex) : GetCall(aCallIndex);
if (call) {
// We have the call either in mCalls or in mGroup. Skip it.
*aContinue = true;
return NS_OK;
}
if (MoveCall(aCallIndex, aIsConference)) {
*aContinue = true;
return NS_OK;
}
@ -622,7 +616,6 @@ Telephony::EnumerateCallState(uint32_t aCallIndex, uint16_t aCallState,
mCalls.Contains(call),
"Should have auto-added new call!");
*aContinue = true;
return NS_OK;
}

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

@ -15,6 +15,7 @@
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
using mozilla::ErrorResult;
// static
already_AddRefed<TelephonyCall>

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

@ -13,6 +13,7 @@
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
using mozilla::ErrorResult;
TelephonyCallGroup::TelephonyCallGroup()
: mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN)

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

@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/telephony/TelephonyFactory.h"
#ifdef MOZ_WIDGET_GONK
#include "nsIGonkTelephonyProvider.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsXULAppAPI.h"
#include "ipc/TelephonyIPCProvider.h"
USING_TELEPHONY_NAMESPACE
/* static */ already_AddRefed<nsITelephonyProvider>
TelephonyFactory::CreateTelephonyProvider()
{
nsCOMPtr<nsITelephonyProvider> provider;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
provider = new TelephonyIPCProvider();
#ifdef MOZ_WIDGET_GONK
} else {
provider = do_CreateInstance(GONK_TELEPHONY_PROVIDER_CONTRACTID);
#endif
}
return provider.forget();
}

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

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_telephony_TelephonyFactory_h
#define mozilla_dom_telephony_TelephonyFactory_h
#include "nsCOMPtr.h"
#include "mozilla/dom/telephony/TelephonyCommon.h"
class nsITelephonyProvider;
BEGIN_TELEPHONY_NAMESPACE
class TelephonyFactory
{
public:
static already_AddRefed<nsITelephonyProvider> CreateTelephonyProvider();
};
END_TELEPHONY_NAMESPACE
#endif // mozilla_dom_telephony_TelephonyFactory_h

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

@ -0,0 +1,525 @@
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
var RIL = {};
Cu.import("resource://gre/modules/ril_consts.js", RIL);
const GONK_TELEPHONYPROVIDER_CONTRACTID =
"@mozilla.org/telephony/gonktelephonyprovider;1";
const GONK_TELEPHONYPROVIDER_CID =
Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}");
const kPrefenceChangedObserverTopic = "nsPref:changed";
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
const nsIAudioManager = Ci.nsIAudioManager;
const nsITelephonyProvider = Ci.nsITelephonyProvider;
const CALL_WAKELOCK_TIMEOUT = 5000;
let DEBUG;
function debug(s) {
dump("TelephonyProvider: " + s + "\n");
}
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
try {
return Cc["@mozilla.org/telephony/audiomanager;1"]
.getService(nsIAudioManager);
} catch (ex) {
//TODO on the phone this should not fall back as silently.
// Fake nsIAudioManager implementation so that we can run the telephony
// code in a non-Gonk build.
if (DEBUG) debug("Using fake audio manager.");
return {
microphoneMuted: false,
masterVolume: 1.0,
masterMuted: false,
phoneState: nsIAudioManager.PHONE_STATE_CURRENT,
_forceForUse: {},
setForceForUse: function setForceForUse(usage, force) {
this._forceForUse[usage] = force;
},
getForceForUse: function setForceForUse(usage) {
return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE;
}
};
}
});
XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService",
"@mozilla.org/power/powermanagerservice;1",
"nsIPowerManagerService");
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
"@mozilla.org/system-message-internal;1",
"nsISystemMessagesInternal");
XPCOMUtils.defineLazyGetter(this, "gRadioInterface", function () {
let ril = Cc["@mozilla.org/ril;1"].getService(Ci["nsIRadioInterfaceLayer"]);
// TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS
return ril.getRadioInterface(0);
});
XPCOMUtils.defineLazyGetter(this, "gPhoneNumberUtils", function () {
let ns = {};
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm", ns);
return ns.PhoneNumberUtils;
});
function TelephonyProvider() {
this._listeners = [];
this._updateDebugFlag();
Services.obs.addObserver(this, kPrefenceChangedObserverTopic, false);
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
}
TelephonyProvider.prototype = {
classID: GONK_TELEPHONYPROVIDER_CID,
classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYPROVIDER_CID,
contractID: GONK_TELEPHONYPROVIDER_CONTRACTID,
classDescription: "TelephonyProvider",
interfaces: [Ci.nsITelephonyProvider,
Ci.nsIGonkTelephonyProvider],
flags: Ci.nsIClassInfo.SINGLETON}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyProvider,
Ci.nsIGonkTelephonyProvider,
Ci.nsIObserver]),
_callRingWakeLock: null,
_callRingWakeLockTimer: null,
_cancelCallRingWakeLockTimer: function _cancelCallRingWakeLockTimer() {
if (this._callRingWakeLockTimer) {
this._callRingWakeLockTimer.cancel();
}
if (this._callRingWakeLock) {
this._callRingWakeLock.unlock();
this._callRingWakeLock = null;
}
},
// An array of nsITelephonyListener instances.
_listeners: null,
_notifyAllListeners: function _notifyAllListeners(aMethodName, aArgs) {
let listeners = this._listeners.slice();
for (let listener of listeners) {
if (this._listeners.indexOf(listener) == -1) {
// Listener has been unregistered in previous run.
continue;
}
let handler = listener[aMethodName];
try {
handler.apply(listener, aArgs);
} catch (e) {
debug("listener for " + aMethodName + " threw an exception: " + e);
}
}
},
/**
* Track the active call and update the audio system as its state changes.
*/
_activeCall: null,
_updateCallAudioState: function _updateCallAudioState(aCall,
aConferenceState) {
if (aConferenceState === nsITelephonyProvider.CALL_STATE_CONNECTED) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
if (this.speakerEnabled) {
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
nsIAudioManager.FORCE_SPEAKER);
}
return;
}
if (aConferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
aConferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
if (!this._activeCall) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
}
return;
}
if (!aCall) {
return;
}
if (aCall.isConference) {
if (this._activeCall && this._activeCall.callIndex == aCall.callIndex) {
this._activeCall = null;
}
return;
}
switch (aCall.state) {
case nsITelephonyProvider.CALL_STATE_DIALING: // Fall through...
case nsITelephonyProvider.CALL_STATE_ALERTING:
case nsITelephonyProvider.CALL_STATE_CONNECTED:
aCall.isActive = true;
this._activeCall = aCall;
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
if (this.speakerEnabled) {
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
nsIAudioManager.FORCE_SPEAKER);
}
if (DEBUG) {
debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
gAudioManager.phoneState);
}
break;
case nsITelephonyProvider.CALL_STATE_INCOMING:
aCall.isActive = false;
if (!this._activeCall) {
// We can change the phone state into RINGTONE only when there's
// no active call.
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
if (DEBUG) {
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: " +
gAudioManager.phoneState);
}
}
break;
case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
aCall.isActive = false;
if (this._activeCall &&
this._activeCall.callIndex == aCall.callIndex) {
// Previously active call is not active now.
this._activeCall = null;
}
if (!this._activeCall) {
// No active call. Disable the audio.
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
if (DEBUG) {
debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
gAudioManager.phoneState);
}
}
break;
}
},
_convertRILCallState: function _convertRILCallState(aState) {
switch (aState) {
case RIL.CALL_STATE_ACTIVE:
return nsITelephonyProvider.CALL_STATE_CONNECTED;
case RIL.CALL_STATE_HOLDING:
return nsITelephonyProvider.CALL_STATE_HELD;
case RIL.CALL_STATE_DIALING:
return nsITelephonyProvider.CALL_STATE_DIALING;
case RIL.CALL_STATE_ALERTING:
return nsITelephonyProvider.CALL_STATE_ALERTING;
case RIL.CALL_STATE_INCOMING:
case RIL.CALL_STATE_WAITING:
return nsITelephonyProvider.CALL_STATE_INCOMING;
default:
throw new Error("Unknown rilCallState: " + aState);
}
},
_convertRILSuppSvcNotification: function _convertRILSuppSvcNotification(aNotification) {
switch (aNotification) {
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD:
return nsITelephonyProvider.NOTIFICATION_REMOTE_HELD;
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED:
return nsITelephonyProvider.NOTIFICATION_REMOTE_RESUMED;
default:
throw new Error("Unknown rilSuppSvcNotification: " + aNotification);
}
},
_validateNumber: function _validateNumber(aNumber) {
// note: isPlainPhoneNumber also accepts USSD and SS numbers
if (gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) {
return true;
}
let errorMsg = RIL.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[RIL.CALL_FAIL_UNOBTAINABLE_NUMBER];
let currentThread = Services.tm.currentThread;
currentThread.dispatch(this.notifyCallError.bind(this, -1, errorMsg),
Ci.nsIThread.DISPATCH_NORMAL);
if (DEBUG) {
debug("Number '" + aNumber + "' doesn't seem to be a viable number. Drop.");
}
return false;
},
_updateDebugFlag: function _updateDebugFlag() {
try {
DEBUG = RIL.DEBUG_RIL ||
Services.prefs.getBoolPref("ril.debugging.enabled");
} catch (e) {}
},
/**
* nsITelephonyProvider interface.
*/
registerListener: function(aListener) {
if (this._listeners.indexOf(aListener) >= 0) {
throw Cr.NS_ERROR_UNEXPECTED;
}
this._listeners.push(aListener);
},
unregisterListener: function(aListener) {
let index = this._listeners.indexOf(aListener);
if (index < 0) {
throw Cr.NS_ERROR_UNEXPECTED;
}
this._listeners.splice(index, 1);
},
enumerateCalls: function(aListener) {
if (DEBUG) debug("Requesting enumeration of calls for callback");
gRadioInterface.sendWorkerMessage("enumerateCalls", null,
(function(response) {
for (let call of response.calls) {
call.state = this._convertRILCallState(call.state);
call.isActive = this._activeCall ?
(call.callIndex == this._activeCall.callIndex) : false;
aListener.enumerateCallState(call.callIndex, call.state, call.number,
call.isActive, call.isOutgoing,
call.isEmergency, call.isConference);
}
aListener.enumerateCallStateComplete();
return false;
}).bind(this));
},
dial: function(aNumber, aIsEmergency) {
if (DEBUG) debug("Dialing " + (aIsEmergency ? "emergency " : "") + aNumber);
// we don't try to be too clever here, as the phone is probably in the
// locked state. Let's just check if it's a number without normalizing
if (!aIsEmergency) {
aNumber = gPhoneNumberUtils.normalize(aNumber);
}
if (this._validateNumber(aNumber)) {
gRadioInterface.sendWorkerMessage("dial", { number: aNumber,
isDialEmergency: aIsEmergency });
}
},
hangUp: function(aCallIndex) {
gRadioInterface.sendWorkerMessage("hangUp", { callIndex: aCallIndex });
},
startTone: function(aDtmfChar) {
gRadioInterface.sendWorkerMessage("startTone", { dtmfChar: aDtmfChar });
},
stopTone: function() {
gRadioInterface.sendWorkerMessage("stopTone");
},
answerCall: function(aCallIndex) {
gRadioInterface.sendWorkerMessage("answerCall", { callIndex: aCallIndex });
},
rejectCall: function(aCallIndex) {
gRadioInterface.sendWorkerMessage("rejectCall", { callIndex: aCallIndex });
},
holdCall: function(aCallIndex) {
gRadioInterface.sendWorkerMessage("holdCall", { callIndex: aCallIndex });
},
resumeCall: function(aCallIndex) {
gRadioInterface.sendWorkerMessage("resumeCall", { callIndex: aCallIndex });
},
conferenceCall: function conferenceCall() {
gRadioInterface.sendWorkerMessage("conferenceCall");
},
separateCall: function separateCall(aCallIndex) {
gRadioInterface.sendWorkerMessage("separateCall", { callIndex: aCallIndex });
},
holdConference: function holdConference() {
gRadioInterface.sendWorkerMessage("holdConference");
},
resumeConference: function resumeConference() {
gRadioInterface.sendWorkerMessage("resumeConference");
},
get microphoneMuted() {
return gAudioManager.microphoneMuted;
},
set microphoneMuted(aMuted) {
if (aMuted == this.microphoneMuted) {
return;
}
gAudioManager.microphoneMuted = aMuted;
if (!this._activeCall) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
}
},
get speakerEnabled() {
let force = gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION);
return (force == nsIAudioManager.FORCE_SPEAKER);
},
set speakerEnabled(aEnabled) {
if (aEnabled == this.speakerEnabled) {
return;
}
let force = aEnabled ? nsIAudioManager.FORCE_SPEAKER :
nsIAudioManager.FORCE_NONE;
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
if (!this._activeCall) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
}
},
/**
* nsIGonkTelephonyProvider interface.
*/
/**
* Handle call disconnects by updating our current state and the audio system.
*/
notifyCallDisconnected: function notifyCallDisconnected(aCall) {
if (DEBUG) debug("handleCallDisconnected: " + JSON.stringify(aCall));
aCall.state = nsITelephonyProvider.CALL_STATE_DISCONNECTED;
let duration = ("started" in aCall && typeof aCall.started == "number") ?
new Date().getTime() - aCall.started : 0;
let data = {
number: aCall.number,
duration: duration,
direction: aCall.isOutgoing ? "outgoing" : "incoming"
};
gSystemMessenger.broadcastMessage("telephony-call-ended", data);
this._updateCallAudioState(aCall, null);
this._notifyAllListeners("callStateChanged", [aCall.callIndex,
aCall.state,
aCall.number,
aCall.isActive,
aCall.isOutgoing,
aCall.isEmergency,
aCall.isConference]);
},
/**
* Handle call error.
*/
notifyCallError: function notifyCallError(aCallIndex, aErrorMsg) {
this._notifyAllListeners("notifyError", [aCallIndex, aErrorMsg]);
},
/**
* Handle an incoming call.
*
* Not much is known about this call at this point, but it's enough
* to start bringing up the Phone app already.
*/
notifyCallRing: function notifyCallRing() {
if (!this._callRingWakeLock) {
this._callRingWakeLock = gPowerManagerService.newWakeLock("cpu");
}
if (!this._callRingWakeLockTimer) {
this._callRingWakeLockTimer =
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
}
this._callRingWakeLockTimer
.initWithCallback(this._cancelCallRingWakeLockTimer.bind(this),
CALL_WAKELOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
gSystemMessenger.broadcastMessage("telephony-new-call", {});
},
/**
* Handle call state changes by updating our current state and the audio
* system.
*/
notifyCallStateChanged: function notifyCallStateChanged(aCall) {
if (DEBUG) debug("handleCallStateChange: " + JSON.stringify(aCall));
aCall.state = this._convertRILCallState(aCall.state);
if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
gSystemMessenger.broadcastMessage("telephony-new-call", {});
}
this._updateCallAudioState(aCall, null);
this._notifyAllListeners("callStateChanged", [aCall.callIndex,
aCall.state,
aCall.number,
aCall.isActive,
aCall.isOutgoing,
aCall.isEmergency,
aCall.isConference]);
},
notifyCdmaCallWaiting: function notifyCdmaCallWaiting(aNumber) {
this._notifyAllListeners("notifyCdmaCallWaiting", [aNumber]);
},
notifySupplementaryService: function notifySupplementaryService(aCallIndex,
aNotification) {
let notification = this._convertRILSuppSvcNotification(aNotification);
this._notifyAllListeners("supplementaryServiceNotification",
[aCallIndex, notification]);
},
notifyConferenceCallStateChanged: function notifyConferenceCallStateChanged(aState) {
if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
aState = aState != null ? convertRILCallState(aState) :
nsITelephonyProvider.CALL_STATE_UNKNOWN;
this._updateCallAudioState(null, aState);
this._notifyAllListeners("conferenceCallStateChanged", [aState]);
},
/**
* nsIObserver interface.
*/
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case kPrefenceChangedObserverTopic:
if (aData === "ril.debugging.enabled") {
this._updateDebugFlag();
}
break;
case kXpcomShutdownObserverTopic:
// Cancel the timer for the call-ring wake lock.
this._cancelCallRingWakeLockTimer();
Services.obs.removeObserver(this, kPrefenceChangedObserverTopic);
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
break;
}
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyProvider]);

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

@ -0,0 +1,2 @@
component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyProvider.js
contract @mozilla.org/telephony/gonktelephonyprovider;1 {67d26434-d063-4d28-9f48-5b3189788155}

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

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PTelephonyRequest;
include TelephonyTypes;
namespace mozilla {
namespace dom {
namespace telephony {
sync protocol PTelephony {
manager PContent;
manages PTelephonyRequest;
child:
NotifyCallError(int32_t aCallIndex, nsString aError);
NotifyCallStateChanged(IPCCallStateData aData);
NotifyCdmaCallWaiting(nsString aNumber);
NotifyConferenceCallStateChanged(uint16_t aCallState);
NotifySupplementaryService(int32_t aCallIndex, uint16_t aNotification);
parent:
/**
* Sent when the child no longer needs to use PTelephony.
*/
__delete__();
/**
* Sent when the child makes an asynchronous request to the parent. It's
* currently only for request call enumeration.
*/
PTelephonyRequest();
RegisterListener();
UnregisterListener();
DialCall(nsString aNumber, bool aIsEmergency);
HangUpCall(uint32_t aCallIndex);
AnswerCall(uint32_t aCallIndex);
RejectCall(uint32_t aCallIndex);
HoldCall(uint32_t aCallIndex);
ResumeCall(uint32_t aCallIndex);
ConferenceCall();
SeparateCall(uint32_t aCallIndex);
HoldConference();
ResumeConference();
StartTone(nsString aTone);
StopTone();
sync GetMicrophoneMuted()
returns (bool aMuted);
SetMicrophoneMuted(bool aMuted);
sync GetSpeakerEnabled()
returns (bool aEnabled);
SetSpeakerEnabled(bool aEnabled);
};
} /* namespace telephony */
} /* namespace dom */
} /* namespace mozilla */

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

@ -0,0 +1,30 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PTelephony;
include TelephonyTypes;
namespace mozilla {
namespace dom {
namespace telephony {
protocol PTelephonyRequest
{
manager PTelephony;
child:
NotifyEnumerateCallState(IPCCallStateData aData);
/**
* Sent when the asynchronous request has completed. It's currently only for
* request call enumeration.
*/
__delete__();
};
} /* namespace telephony */
} /* namespace dom */
} /* namespace mozilla */

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

@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/telephony/TelephonyChild.h"
USING_TELEPHONY_NAMESPACE
/*******************************************************************************
* TelephonyChild
******************************************************************************/
TelephonyChild::TelephonyChild(nsITelephonyListener* aListener)
: mListener(aListener)
{
MOZ_ASSERT(aListener);
}
void
TelephonyChild::ActorDestroy(ActorDestroyReason aWhy)
{
mListener = nullptr;
}
PTelephonyRequestChild*
TelephonyChild::AllocPTelephonyRequestChild()
{
MOZ_CRASH("Caller is supposed to manually construct a request!");
}
bool
TelephonyChild::DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor)
{
delete aActor;
return true;
}
bool
TelephonyChild::RecvNotifyCallError(const int32_t& aCallIndex,
const nsString& aError)
{
MOZ_ASSERT(mListener);
mListener->NotifyError(aCallIndex, aError);
return true;
}
bool
TelephonyChild::RecvNotifyCallStateChanged(const IPCCallStateData& aData)
{
MOZ_ASSERT(mListener);
mListener->CallStateChanged(aData.callIndex(),
aData.callState(),
aData.number(),
aData.isActive(),
aData.isOutGoing(),
aData.isEmergency(),
aData.isConference());
return true;
}
bool
TelephonyChild::RecvNotifyCdmaCallWaiting(const nsString& aNumber)
{
MOZ_ASSERT(mListener);
mListener->NotifyCdmaCallWaiting(aNumber);
return true;
}
bool
TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState)
{
MOZ_ASSERT(mListener);
mListener->ConferenceCallStateChanged(aCallState);
return true;
}
bool
TelephonyChild::RecvNotifySupplementaryService(const int32_t& aCallIndex,
const uint16_t& aNotification)
{
MOZ_ASSERT(mListener);
mListener->SupplementaryServiceNotification(aCallIndex, aNotification);
return true;
}
/*******************************************************************************
* TelephonyRequestChild
******************************************************************************/
TelephonyRequestChild::TelephonyRequestChild(nsITelephonyListener* aListener)
: mListener(aListener)
{
MOZ_ASSERT(aListener);
}
void
TelephonyRequestChild::ActorDestroy(ActorDestroyReason aWhy)
{
mListener = nullptr;
}
bool
TelephonyRequestChild::Recv__delete__()
{
MOZ_ASSERT(mListener);
mListener->EnumerateCallStateComplete();
return true;
}
bool
TelephonyRequestChild::RecvNotifyEnumerateCallState(const IPCCallStateData& aData)
{
MOZ_ASSERT(mListener);
mListener->EnumerateCallState(aData.callIndex(),
aData.callState(),
aData.number(),
aData.isActive(),
aData.isOutGoing(),
aData.isEmergency(),
aData.isConference());
return true;
}

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

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_telephony_TelephonyChild_h
#define mozilla_dom_telephony_TelephonyChild_h
#include "mozilla/dom/telephony/TelephonyCommon.h"
#include "mozilla/dom/telephony/PTelephonyChild.h"
#include "mozilla/dom/telephony/PTelephonyRequestChild.h"
#include "nsITelephonyProvider.h"
BEGIN_TELEPHONY_NAMESPACE
class TelephonyChild : public PTelephonyChild
{
public:
TelephonyChild(nsITelephonyListener* aListener);
protected:
virtual ~TelephonyChild() {}
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual PTelephonyRequestChild*
AllocPTelephonyRequestChild() MOZ_OVERRIDE;
virtual bool
DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor) MOZ_OVERRIDE;
virtual bool
RecvNotifyCallError(const int32_t& aCallIndex,
const nsString& aError) MOZ_OVERRIDE;
virtual bool
RecvNotifyCallStateChanged(const IPCCallStateData& aData) MOZ_OVERRIDE;
virtual bool
RecvNotifyCdmaCallWaiting(const nsString& aNumber) MOZ_OVERRIDE;
virtual bool
RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState) MOZ_OVERRIDE;
virtual bool
RecvNotifySupplementaryService(const int32_t& aCallIndex,
const uint16_t& aNotification) MOZ_OVERRIDE;
private:
nsCOMPtr<nsITelephonyListener> mListener;
};
class TelephonyRequestChild : public PTelephonyRequestChild
{
public:
TelephonyRequestChild(nsITelephonyListener* aListener);
protected:
virtual ~TelephonyRequestChild() {}
virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
Recv__delete__() MOZ_OVERRIDE;
virtual bool
RecvNotifyEnumerateCallState(const IPCCallStateData& aData) MOZ_OVERRIDE;
private:
nsCOMPtr<nsITelephonyListener> mListener;
};
END_TELEPHONY_NAMESPACE
#endif // mozilla_dom_telephony_TelephonyChild_h

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

@ -0,0 +1,258 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/telephony/TelephonyChild.h"
#include "ipc/TelephonyIPCProvider.h"
USING_TELEPHONY_NAMESPACE
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS2(TelephonyIPCProvider,
nsITelephonyProvider,
nsITelephonyListener)
TelephonyIPCProvider::TelephonyIPCProvider()
{
// Deallocated in ContentChild::DeallocPTelephonyChild().
mPTelephonyChild = new TelephonyChild(this);
ContentChild::GetSingleton()->SendPTelephonyConstructor(mPTelephonyChild);
}
TelephonyIPCProvider::~TelephonyIPCProvider()
{
mPTelephonyChild->Send__delete__(mPTelephonyChild);
mPTelephonyChild = nullptr;
}
/*
* Implementation of nsITelephonyProvider.
*/
NS_IMETHODIMP
TelephonyIPCProvider::RegisterListener(nsITelephonyListener *aListener)
{
MOZ_ASSERT(!mListeners.Contains(aListener));
// nsTArray doesn't fail.
mListeners.AppendElement(aListener);
if (mListeners.Length() == 1) {
mPTelephonyChild->SendRegisterListener();
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::UnregisterListener(nsITelephonyListener *aListener)
{
MOZ_ASSERT(mListeners.Contains(aListener));
// We always have the element here, so it can't fail.
mListeners.RemoveElement(aListener);
if (!mListeners.Length()) {
mPTelephonyChild->SendUnregisterListener();
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::EnumerateCalls(nsITelephonyListener *aListener)
{
// Life time of newly allocated TelephonyRequestChild instance is managed by
// IPDL itself.
TelephonyRequestChild* actor = new TelephonyRequestChild(aListener);
mPTelephonyChild->SendPTelephonyRequestConstructor(actor);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::Dial(const nsAString& aNumber,
bool aIsEmergency)
{
mPTelephonyChild->SendDialCall(nsString(aNumber), aIsEmergency);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::HangUp(uint32_t aCallIndex)
{
mPTelephonyChild->SendHangUpCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::AnswerCall(uint32_t aCallIndex)
{
mPTelephonyChild->SendAnswerCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::RejectCall(uint32_t aCallIndex)
{
mPTelephonyChild->SendRejectCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::HoldCall(uint32_t aCallIndex)
{
mPTelephonyChild->SendHoldCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::ResumeCall(uint32_t aCallIndex)
{
mPTelephonyChild->SendResumeCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::ConferenceCall()
{
mPTelephonyChild->SendConferenceCall();
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::SeparateCall(uint32_t aCallIndex)
{
mPTelephonyChild->SendSeparateCall(aCallIndex);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::HoldConference()
{
mPTelephonyChild->SendHoldConference();
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::ResumeConference()
{
mPTelephonyChild->SendResumeConference();
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::StartTone(const nsAString& aDtmfChar)
{
mPTelephonyChild->SendStartTone(nsString(aDtmfChar));
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::StopTone()
{
mPTelephonyChild->SendStopTone();
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::GetMicrophoneMuted(bool* aMuted)
{
mPTelephonyChild->SendGetMicrophoneMuted(aMuted);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::SetMicrophoneMuted(bool aMuted)
{
mPTelephonyChild->SendSetMicrophoneMuted(aMuted);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::GetSpeakerEnabled(bool* aEnabled)
{
mPTelephonyChild->SendGetSpeakerEnabled(aEnabled);
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::SetSpeakerEnabled(bool aEnabled)
{
mPTelephonyChild->SendSetSpeakerEnabled(aEnabled);
return NS_OK;
}
// nsITelephonyListener
NS_IMETHODIMP
TelephonyIPCProvider::CallStateChanged(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->CallStateChanged(aCallIndex, aCallState, aNumber,
aIsActive, aIsOutgoing, aIsEmergency,
aIsConference);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::ConferenceCallStateChanged(uint16_t aCallState)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->ConferenceCallStateChanged(aCallState);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::EnumerateCallStateComplete()
{
MOZ_CRASH("Not a EnumerateCalls request!");
}
NS_IMETHODIMP
TelephonyIPCProvider::EnumerateCallState(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
MOZ_CRASH("Not a EnumerateCalls request!");
}
NS_IMETHODIMP
TelephonyIPCProvider::NotifyCdmaCallWaiting(const nsAString& aNumber)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->NotifyCdmaCallWaiting(aNumber);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::NotifyError(int32_t aCallIndex,
const nsAString& aError)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->NotifyError(aCallIndex, aError);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCProvider::SupplementaryServiceNotification(int32_t aCallIndex,
uint16_t aNotification)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->SupplementaryServiceNotification(aCallIndex, aNotification);
}
return NS_OK;
}

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

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_telephony_TelephonyIPCProvider_h
#define mozilla_dom_telephony_TelephonyIPCProvider_h
#include "mozilla/dom/telephony/TelephonyCommon.h"
#include "mozilla/Attributes.h"
#include "nsITelephonyProvider.h"
BEGIN_TELEPHONY_NAMESPACE
class PTelephonyChild;
class TelephonyIPCProvider MOZ_FINAL : public nsITelephonyProvider
, public nsITelephonyListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITELEPHONYPROVIDER
NS_DECL_NSITELEPHONYLISTENER
TelephonyIPCProvider();
protected:
virtual ~TelephonyIPCProvider();
private:
nsTArray<nsCOMPtr<nsITelephonyListener> > mListeners;
PTelephonyChild* mPTelephonyChild;
};
END_TELEPHONY_NAMESPACE
#endif // mozilla_dom_telephony_TelephonyIPCProvider_h

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

@ -0,0 +1,448 @@
/* -*- Mode: C++ tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/telephony/TelephonyParent.h"
USING_TELEPHONY_NAMESPACE
/*******************************************************************************
* TelephonyParent
******************************************************************************/
NS_IMPL_ISUPPORTS1(TelephonyParent, nsITelephonyListener)
TelephonyParent::TelephonyParent()
: mActorDestroyed(false)
, mRegistered(false)
{
}
void
TelephonyParent::ActorDestroy(ActorDestroyReason why)
{
// The child process could die before this asynchronous notification, in which
// case ActorDestroy() was called and mActorDestroyed is set to true. Return
// an error here to avoid sending a message to the dead process.
mActorDestroyed = true;
// Try to unregister listener if we're still registered.
RecvUnregisterListener();
}
bool
TelephonyParent::RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor)
{
TelephonyRequestParent* actor = static_cast<TelephonyRequestParent*>(aActor);
return actor->DoRequest();
}
PTelephonyRequestParent*
TelephonyParent::AllocPTelephonyRequestParent()
{
TelephonyRequestParent* actor = new TelephonyRequestParent();
// Add an extra ref for IPDL. Will be released in
// TelephonyParent::DeallocPTelephonyRequestParent().
NS_ADDREF(actor);
return actor;
}
bool
TelephonyParent::DeallocPTelephonyRequestParent(PTelephonyRequestParent* aActor)
{
// TelephonyRequestParent is refcounted, must not be freed manually.
static_cast<TelephonyRequestParent*>(aActor)->Release();
return true;
}
bool
TelephonyParent::Recv__delete__()
{
return true; // Unregister listener in TelephonyParent::ActorDestroy().
}
bool
TelephonyParent::RecvRegisterListener()
{
NS_ENSURE_TRUE(!mRegistered, true);
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
mRegistered = NS_SUCCEEDED(provider->RegisterListener(this));
return true;
}
bool
TelephonyParent::RecvUnregisterListener()
{
NS_ENSURE_TRUE(mRegistered, true);
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
mRegistered = !NS_SUCCEEDED(provider->UnregisterListener(this));
return true;
}
bool
TelephonyParent::RecvDialCall(const nsString& aNumber,
const bool& aIsEmergency)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->Dial(aNumber, aIsEmergency);
return true;
}
bool
TelephonyParent::RecvHangUpCall(const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->HangUp(aCallIndex);
return true;
}
bool
TelephonyParent::RecvAnswerCall(const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->AnswerCall(aCallIndex);
return true;
}
bool
TelephonyParent::RecvRejectCall(const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->RejectCall(aCallIndex);
return true;
}
bool
TelephonyParent::RecvHoldCall(const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->HoldCall(aCallIndex);
return true;
}
bool
TelephonyParent::RecvResumeCall(const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->ResumeCall(aCallIndex);
return true;
}
bool
TelephonyParent::RecvConferenceCall()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->ConferenceCall();
return true;
}
bool
TelephonyParent::RecvSeparateCall(const uint32_t& aCallState)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->SeparateCall(aCallState);
return true;
}
bool
TelephonyParent::RecvHoldConference()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->HoldConference();
return true;
}
bool
TelephonyParent::RecvResumeConference()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->ResumeConference();
return true;
}
bool
TelephonyParent::RecvStartTone(const nsString& aTone)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->StartTone(aTone);
return true;
}
bool
TelephonyParent::RecvStopTone()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->StopTone();
return true;
}
bool
TelephonyParent::RecvGetMicrophoneMuted(bool* aMuted)
{
*aMuted = false;
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->GetMicrophoneMuted(aMuted);
return true;
}
bool
TelephonyParent::RecvSetMicrophoneMuted(const bool& aMuted)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->SetMicrophoneMuted(aMuted);
return true;
}
bool
TelephonyParent::RecvGetSpeakerEnabled(bool* aEnabled)
{
*aEnabled = false;
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->GetSpeakerEnabled(aEnabled);
return true;
}
bool
TelephonyParent::RecvSetSpeakerEnabled(const bool& aEnabled)
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE(provider, true);
provider->SetSpeakerEnabled(aEnabled);
return true;
}
// nsITelephonyListener
NS_IMETHODIMP
TelephonyParent::CallStateChanged(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), aIsActive,
aIsOutgoing, aIsEmergency, aIsConference);
return SendNotifyCallStateChanged(data) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::ConferenceCallStateChanged(uint16_t aCallState)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifyConferenceCallStateChanged(aCallState) ? NS_OK
: NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::EnumerateCallStateComplete()
{
MOZ_CRASH("Not a EnumerateCalls request!");
}
NS_IMETHODIMP
TelephonyParent::EnumerateCallState(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
MOZ_CRASH("Not a EnumerateCalls request!");
}
NS_IMETHODIMP
TelephonyParent::NotifyCdmaCallWaiting(const nsAString& aNumber)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifyCdmaCallWaiting(nsString(aNumber)) ? NS_OK
: NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::NotifyError(int32_t aCallIndex,
const nsAString& aError)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifyCallError(aCallIndex, nsString(aError)) ? NS_OK
: NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::SupplementaryServiceNotification(int32_t aCallIndex,
uint16_t aNotification)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifySupplementaryService(aCallIndex, aNotification)
? NS_OK : NS_ERROR_FAILURE;
}
/*******************************************************************************
* TelephonyRequestParent
******************************************************************************/
NS_IMPL_ISUPPORTS1(TelephonyRequestParent, nsITelephonyListener)
TelephonyRequestParent::TelephonyRequestParent()
: mActorDestroyed(false)
{
}
void
TelephonyRequestParent::ActorDestroy(ActorDestroyReason why)
{
// The child process could die before this asynchronous notification, in which
// case ActorDestroy() was called and mActorDestroyed is set to true. Return
// an error here to avoid sending a message to the dead process.
mActorDestroyed = true;
}
bool
TelephonyRequestParent::DoRequest()
{
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
if (provider) {
rv = provider->EnumerateCalls(this);
}
if (NS_FAILED(rv)) {
return NS_SUCCEEDED(EnumerateCallStateComplete());
}
return true;
}
// nsITelephonyListener
NS_IMETHODIMP
TelephonyRequestParent::CallStateChanged(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::ConferenceCallStateChanged(uint16_t aCallState)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::EnumerateCallStateComplete()
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return Send__delete__(this) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyRequestParent::EnumerateCallState(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), aIsActive,
aIsOutgoing, aIsEmergency, aIsConference);
return SendNotifyEnumerateCallState(data) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyRequestParent::NotifyCdmaCallWaiting(const nsAString& aNumber)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::NotifyError(int32_t aCallIndex,
const nsAString& aError)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::SupplementaryServiceNotification(int32_t aCallIndex,
uint16_t aNotification)
{
MOZ_CRASH("Not a TelephonyParent!");
}

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

@ -0,0 +1,128 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_telephony_TelephonyParent_h
#define mozilla_dom_telephony_TelephonyParent_h
#include "mozilla/dom/telephony/TelephonyCommon.h"
#include "mozilla/dom/telephony/PTelephonyParent.h"
#include "mozilla/dom/telephony/PTelephonyRequestParent.h"
#include "nsITelephonyProvider.h"
BEGIN_TELEPHONY_NAMESPACE
class TelephonyParent : public PTelephonyParent
, public nsITelephonyListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITELEPHONYLISTENER
TelephonyParent();
protected:
virtual ~TelephonyParent() {}
virtual void
ActorDestroy(ActorDestroyReason why);
virtual bool
RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor) MOZ_OVERRIDE;
virtual PTelephonyRequestParent*
AllocPTelephonyRequestParent() MOZ_OVERRIDE;
virtual bool
DeallocPTelephonyRequestParent(PTelephonyRequestParent* aActor) MOZ_OVERRIDE;
virtual bool
Recv__delete__() MOZ_OVERRIDE;
virtual bool
RecvRegisterListener() MOZ_OVERRIDE;
virtual bool
RecvUnregisterListener() MOZ_OVERRIDE;
virtual bool
RecvDialCall(const nsString& aNumber,
const bool& aIsEmergency) MOZ_OVERRIDE;
virtual bool
RecvHangUpCall(const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvAnswerCall(const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvRejectCall(const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvHoldCall(const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvResumeCall(const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvConferenceCall() MOZ_OVERRIDE;
virtual bool
RecvSeparateCall(const uint32_t& callIndex) MOZ_OVERRIDE;
virtual bool
RecvHoldConference() MOZ_OVERRIDE;
virtual bool
RecvResumeConference() MOZ_OVERRIDE;
virtual bool
RecvStartTone(const nsString& aTone) MOZ_OVERRIDE;
virtual bool
RecvStopTone() MOZ_OVERRIDE;
virtual bool
RecvGetMicrophoneMuted(bool* aMuted) MOZ_OVERRIDE;
virtual bool
RecvSetMicrophoneMuted(const bool& aMuted) MOZ_OVERRIDE;
virtual bool
RecvGetSpeakerEnabled(bool* aEnabled) MOZ_OVERRIDE;
virtual bool
RecvSetSpeakerEnabled(const bool& aEnabled) MOZ_OVERRIDE;
private:
bool mActorDestroyed;
bool mRegistered;
};
class TelephonyRequestParent : public PTelephonyRequestParent
, public nsITelephonyListener
{
friend class TelephonyParent;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITELEPHONYLISTENER
protected:
TelephonyRequestParent();
virtual ~TelephonyRequestParent() {}
virtual void
ActorDestroy(ActorDestroyReason why);
private:
bool mActorDestroyed;
bool
DoRequest();
};
END_TELEPHONY_NAMESPACE
#endif /* mozilla_dom_telephony_TelephonyParent_h */

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

@ -0,0 +1,24 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace mozilla {
namespace dom {
namespace telephony {
struct IPCCallStateData
{
uint32_t callIndex;
uint16_t callState;
nsString number;
bool isActive;
bool isOutGoing;
bool isEmergency;
bool isConference;
};
} /* namespace telephony */
} /* namespace dom */
} /* namespace mozilla */

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

@ -12,17 +12,47 @@ XPIDL_MODULE = 'dom_telephony'
MODULE = 'dom'
EXPORTS.mozilla.dom.telephony += [
'CallEvent.h',
'CallsList.h',
'Telephony.h',
'TelephonyCall.h',
'TelephonyCallGroup.h',
'TelephonyCommon.h',
'TelephonyFactory.h',
'ipc/TelephonyChild.h',
'ipc/TelephonyParent.h',
]
CPP_SOURCES += [
'CallEvent.cpp',
'CallsList.cpp',
'Telephony.cpp',
'TelephonyCall.cpp',
'TelephonyCallGroup.cpp',
'TelephonyFactory.cpp',
'ipc/TelephonyChild.cpp',
'ipc/TelephonyIPCProvider.cpp',
'ipc/TelephonyParent.cpp',
]
IPDL_SOURCES += [
'ipc/PTelephony.ipdl',
'ipc/PTelephonyRequest.ipdl',
'ipc/TelephonyTypes.ipdlh'
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
XPIDL_SOURCES += [
'nsIGonkTelephonyProvider.idl',
]
EXTRA_COMPONENTS += [
'gonk/TelephonyProvider.js',
'gonk/TelephonyProvider.manifest',
]
FAIL_ON_WARNINGS = True
LIBXUL_LIBRARY = True
LIBRARY_NAME = 'domtelephony_s'

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

@ -0,0 +1,31 @@
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsITelephonyProvider.idl"
%{C++
#define GONK_TELEPHONY_PROVIDER_CONTRACTID \
"@mozilla.org/telephony/gonktelephonyprovider;1"
%}
[scriptable, uuid(0d106c7e-ba47-48ee-ba48-c92002d401b6)]
interface nsIGonkTelephonyProvider : nsITelephonyProvider
{
void notifyCallDisconnected(in jsval call);
void notifyCallError(in long callIndex,
in AString error);
void notifyCallRing();
void notifyCallStateChanged(in jsval call);
void notifyCdmaCallWaiting(in AString number);
void notifySupplementaryService(in long callIndex,
in AString notification);
void notifyConferenceCallStateChanged(in unsigned short state);
};

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

@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, uuid(a5818719-e1b6-4fdc-8551-006055fa9996)]
[scriptable, uuid(3aa42e77-7c2b-43a1-b105-7be094b0817a)]
interface nsITelephonyListener : nsISupports
{
/**
@ -67,15 +67,14 @@ interface nsITelephonyListener : nsISupports
* Indicates whether this call is outgoing or incoming.
* @param isConference
* Indicates whether this call is a conference call.
* @return true to continue enumeration or false to cancel.
*/
boolean enumerateCallState(in unsigned long callIndex,
in unsigned short callState,
in AString number,
in boolean isActive,
in boolean isOutgoing,
in boolean isEmergency,
in boolean isConference);
void enumerateCallState(in unsigned long callIndex,
in unsigned short callState,
in AString number,
in boolean isActive,
in boolean isOutgoing,
in boolean isEmergency,
in boolean isConference);
/**
* Notify when RIL receives supplementary service notification.
@ -108,11 +107,18 @@ interface nsITelephonyListener : nsISupports
void notifyCdmaCallWaiting(in AString number);
};
%{C++
#define TELEPHONY_PROVIDER_CID \
{ 0x9cf8aa52, 0x7c1c, 0x4cde, { 0x97, 0x4e, 0xed, 0x2a, 0xa0, 0xe7, 0x35, 0xfa } }
#define TELEPHONY_PROVIDER_CONTRACTID \
"@mozilla.org/telephony/telephonyprovider;1"
%}
/**
* XPCOM component (in the content process) that provides the telephony
* information.
*/
[scriptable, uuid(45a2f856-4e07-499a-94c6-624f90c3345b)]
[scriptable, uuid(effca006-1ca8-47f7-9bab-1323f90a14ec)]
interface nsITelephonyProvider : nsISupports
{
const unsigned short CALL_STATE_UNKNOWN = 0;
@ -135,8 +141,8 @@ interface nsITelephonyProvider : nsISupports
* RadioInterfaceLayer in the chrome process. Only a content process that has
* the 'telephony' permission is allowed to register.
*/
void registerTelephonyMsg(in nsITelephonyListener listener);
void unregisterTelephonyMsg(in nsITelephonyListener listener);
void registerListener(in nsITelephonyListener listener);
void unregisterListener(in nsITelephonyListener listener);
/**
* Will continue calling listener.enumerateCallState until the listener
@ -147,8 +153,8 @@ interface nsITelephonyProvider : nsISupports
/**
* Functionality for making and managing phone calls.
*/
void dial(in DOMString number);
void dialEmergency(in DOMString number);
void dial(in DOMString number,
in boolean isEmergency);
void hangUp(in unsigned long callIndex);
void startTone(in DOMString dtmfChar);

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

@ -102,7 +102,7 @@ var interfaceNamesInGlobalScope =
{name: "BluetoothStatusChangedEvent", b2g: true},
{name: "BoxObject", xbl: true},
{name: "BrowserFeedWriter", desktop: true},
{name: "CallEvent", b2g: true},
"CallEvent",
"CameraCapabilities",
"CameraControl",
"CameraManager",
@ -531,9 +531,9 @@ var interfaceNamesInGlobalScope =
"SVGViewElement",
"SVGZoomAndPan",
"SVGZoomEvent",
{name: "Telephony", b2g: true},
{name: "TelephonyCall", b2g: true},
{name: "TelephonyCallGroup", b2g: true},
"Telephony",
"TelephonyCall",
"TelephonyCallGroup",
"Text",
"TextDecoder",
"TextEncoder",

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

@ -88,7 +88,7 @@ interface BluetoothAdapter : EventTarget {
[Creator, Throws]
DOMRequest getPairedDevices();
[Creator, Throws]
DOMRequest getConnectedDevices(unsigned short profile);
DOMRequest getConnectedDevices(unsigned short serviceUuid);
[Creator, Throws]
DOMRequest setPinCode(DOMString deviceAddress, DOMString pinCode);
[Creator, Throws]
@ -101,13 +101,19 @@ interface BluetoothAdapter : EventTarget {
* To check the value of service UUIDs, please check "Bluetooth Assigned
* Numbers" / "Service Discovery Protocol" for more information.
*
* @param deviceAddress Remote device address
* @param profile 2-octets service UUID
* Note that service UUID is optional. If it isn't passed when calling
* Connect, multiple profiles are tried sequentially based on the class of
* device (CoD). If it isn't passed when calling Disconnect, all connected
* profiles are going to be closed.
*
* @param device Remote device
* @param profile 2-octets service UUID. This is optional.
*/
[Creator, Throws]
DOMRequest connect(DOMString deviceAddress, unsigned short profile);
DOMRequest connect(BluetoothDevice device, optional unsigned short serviceUuid);
[Creator, Throws]
DOMRequest disconnect(unsigned short profile);
DOMRequest disconnect(BluetoothDevice device, optional unsigned short serviceUuid);
// One device can only send one file at a time
[Creator, Throws]

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

@ -34,6 +34,8 @@ webidl_files = \
BiquadFilterNode.webidl \
Blob.webidl \
BrowserElementDictionaries.webidl \
CallEvent.webidl \
CallsList.webidl \
CameraControl.webidl \
CameraManager.webidl \
CanvasRenderingContext2D.webidl \
@ -359,6 +361,9 @@ webidl_files = \
SVGViewElement.webidl \
SVGZoomAndPan.webidl \
SVGZoomEvent.webidl \
Telephony.webidl \
TelephonyCall.webidl \
TelephonyCallGroup.webidl \
Text.webidl \
TextDecoder.webidl \
TextEncoder.webidl \
@ -445,12 +450,8 @@ endif
ifdef MOZ_B2G_RIL
webidl_files += \
CallsList.webidl \
MozStkCommandEvent.webidl \
MozVoicemail.webidl \
Telephony.webidl \
TelephonyCall.webidl \
TelephonyCallGroup.webidl \
$(NULL)
endif
@ -495,7 +496,6 @@ endif
ifdef MOZ_B2G_RIL
webidl_files += \
CallEvent.webidl \
CFStateChangeEvent.webidl \
DataErrorEvent.webidl \
IccCardLockErrorEvent.webidl \

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

@ -208,6 +208,7 @@ CompositableClient::RemoveTextureClient(TextureClient* aClient)
MOZ_ASSERT(aClient);
mTexturesToRemove.AppendElement(aClient->GetID());
aClient->ClearID();
aClient->MarkInvalid();
}
void

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

@ -116,6 +116,12 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer,
// fast path: no need to allocate and/or copy image data
RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient();
if (texture->IsSharedWithCompositor()) {
// XXX - temporary fix for bug 911941
// This will be changed with bug 912907
return false;
}
if (mFrontBuffer) {
RemoveTextureClient(mFrontBuffer);
}

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

@ -39,6 +39,7 @@ TextureClient::TextureClient(TextureFlags aFlags)
: mID(0)
, mFlags(aFlags)
, mShared(false)
, mValid(true)
{}
TextureClient::~TextureClient()
@ -64,6 +65,7 @@ TextureClient::ShouldDeallocateInDestructor() const
bool
ShmemTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated() || GetFormat() == gfx::FORMAT_UNKNOWN) {
return false;
}
@ -82,6 +84,7 @@ ShmemTextureClient::GetAllocator() const
bool
ShmemTextureClient::Allocate(uint32_t aSize)
{
MOZ_ASSERT(IsValid());
ipc::SharedMemory::SharedMemoryType memType = OptimalShmemType();
mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
return mAllocated;
@ -90,6 +93,7 @@ ShmemTextureClient::Allocate(uint32_t aSize)
uint8_t*
ShmemTextureClient::GetBuffer() const
{
MOZ_ASSERT(IsValid());
if (mAllocated) {
return mShmem.get<uint8_t>();
}
@ -99,6 +103,7 @@ ShmemTextureClient::GetBuffer() const
size_t
ShmemTextureClient::GetBufferSize() const
{
MOZ_ASSERT(IsValid());
return mShmem.Size<uint8_t>();
}
@ -124,6 +129,7 @@ ShmemTextureClient::~ShmemTextureClient()
bool
MemoryTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated() || GetFormat() == gfx::FORMAT_UNKNOWN) {
return false;
}
@ -177,6 +183,7 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
{
MOZ_ASSERT(aSurface);
MOZ_ASSERT(!IsImmutable());
MOZ_ASSERT(IsValid());
ImageDataSerializer serializer(GetBuffer());
if (!serializer.IsValid()) {
@ -204,6 +211,8 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
already_AddRefed<gfxASurface>
BufferTextureClient::GetAsSurface()
{
MOZ_ASSERT(IsValid());
ImageDataSerializer serializer(GetBuffer());
if (!serializer.IsValid()) {
return nullptr;
@ -217,6 +226,7 @@ BufferTextureClient::GetAsSurface()
bool
BufferTextureClient::AllocateForSurface(gfx::IntSize aSize)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This textureClient cannot use YCbCr data");
int bufSize
@ -235,6 +245,7 @@ BufferTextureClient::UpdateYCbCr(const PlanarYCbCrImage::Data& aData)
{
MOZ_ASSERT(mFormat == gfx::FORMAT_YUV, "This textureClient can only use YCbCr data");
MOZ_ASSERT(!IsImmutable());
MOZ_ASSERT(IsValid());
MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
YCbCrImageDataSerializer serializer(GetBuffer());
@ -260,6 +271,8 @@ BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode)
{
MOZ_ASSERT(IsValid());
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
aCbCrSize);
if (!Allocate(bufSize)) {

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

@ -106,7 +106,7 @@ public:
virtual bool Lock(OpenMode aMode)
{
return true;
return IsValid();
}
virtual void Unlock() {}
@ -158,6 +158,15 @@ public:
bool IsSharedWithCompositor() const { return mShared; }
bool ShouldDeallocateInDestructor() const;
/**
* If this method returns false users of TextureClient are not allowed
* to access the shared data.
*/
bool IsValid() const { return mValid; }
void MarkInvalid() { mValid = false; }
protected:
void AddFlags(TextureFlags aFlags)
{
@ -175,6 +184,7 @@ protected:
uint64_t mID;
TextureFlags mFlags;
bool mShared;
bool mValid;
};
/**

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

@ -27,6 +27,7 @@ using namespace mozilla::ipc;
SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable)
: PlanarYCbCrImage(nullptr)
, mCompositable(aCompositable)
{
mTextureClient = aCompositable->CreateBufferTextureClient(gfx::FORMAT_YUV);
MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);

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

@ -119,6 +119,7 @@ public:
private:
RefPtr<BufferTextureClient> mTextureClient;
RefPtr<ImageClient> mCompositable;
};
} // namespace

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

@ -48,6 +48,7 @@ GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize
{
MOZ_ASSERT(aActor);
MOZ_ASSERT(!IsAllocated());
MOZ_ASSERT(IsValid());
mGrallocActor = aActor;
mGraphicBuffer = aActor->GetGraphicBuffer();
mSize = aSize;
@ -56,6 +57,7 @@ GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize
bool
GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}
@ -67,6 +69,7 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
bool
GrallocTextureClientOGL::Lock(OpenMode aMode)
{
MOZ_ASSERT(IsValid());
// XXX- it would be cleaner to take the openMode into account or to check
// that aMode is coherent with mGrallocFlags (which carries more information
// than OpenMode).
@ -87,6 +90,7 @@ GrallocTextureClientOGL::Unlock()
uint8_t*
GrallocTextureClientOGL::GetBuffer() const
{
MOZ_ASSERT(IsValid());
NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
return mMappedBuffer;
}
@ -94,6 +98,7 @@ GrallocTextureClientOGL::GetBuffer() const
bool
GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mCompositable);
ISurfaceAllocator* allocator = mCompositable->GetForwarder();
@ -130,6 +135,7 @@ GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize)
bool
GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode)
{
MOZ_ASSERT(IsValid());
return AllocateGralloc(aYSize,
HAL_PIXEL_FORMAT_YV12,
android::GraphicBuffer::USAGE_SW_READ_OFTEN);
@ -140,6 +146,7 @@ GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
uint32_t aAndroidFormat,
uint32_t aUsage)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mCompositable);
ISurfaceAllocator* allocator = mCompositable->GetForwarder();

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

@ -34,6 +34,7 @@ SharedTextureClientOGL::~SharedTextureClientOGL()
bool
SharedTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}
@ -48,6 +49,7 @@ SharedTextureClientOGL::InitWith(gl::SharedTextureHandle aHandle,
gl::SharedTextureShareType aShareType,
bool aInverted)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(!IsAllocated());
mHandle = aHandle;
mSize = aSize;

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

@ -76,7 +76,7 @@ public:
MOZ_ASSERT(NS_IsMainThread());
return mConsumer == nullptr;
}
void ShutdownOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
@ -134,17 +134,17 @@ public:
ClearDelayedConnectTask();
}
/**
/**
* Connect to a socket
*/
void Connect();
/**
/**
* Run bind/listen to prepare for further runs of accept()
*/
void Listen();
/**
/**
* Accept an incoming connection
*/
void Accept();
@ -217,7 +217,7 @@ private:
*/
ScopedClose mFd;
/**
/**
* Connector object used to create the connection we are currently using.
*/
nsAutoPtr<UnixSocketConnector> mConnector;
@ -480,7 +480,7 @@ void ShutdownSocketTask::Run()
NS_ENSURE_SUCCESS_VOID(rv);
}
void
void
UnixSocketImpl::Accept()
{
MOZ_ASSERT(!NS_IsMainThread());
@ -677,8 +677,8 @@ UnixSocketConsumer::SendSocketData(const nsACString& aStr)
}
MOZ_ASSERT(!mImpl->IsShutdownOnMainThread());
UnixSocketRawData* d = new UnixSocketRawData(aStr.Length());
memcpy(d->mData, aStr.BeginReading(), aStr.Length());
UnixSocketRawData* d = new UnixSocketRawData(aStr.BeginReading(),
aStr.Length());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new SocketSendTask(this, mImpl, d));
return true;
@ -717,8 +717,9 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
if (status == SOCKET_CONNECTED) {
// Read all of the incoming data.
while (true) {
uint8_t data[MAX_READ_SIZE];
ssize_t ret = read(aFd, data, MAX_READ_SIZE);
nsAutoPtr<UnixSocketRawData> incoming(new UnixSocketRawData(MAX_READ_SIZE));
ssize_t ret = read(aFd, incoming->mData, incoming->mSize);
if (ret <= 0) {
if (ret == -1) {
if (errno == EINTR) {
@ -743,13 +744,13 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
return;
}
UnixSocketRawData* incoming = new UnixSocketRawData(ret);
memcpy(incoming->mData, data, ret);
nsRefPtr<SocketReceiveTask> t = new SocketReceiveTask(this, incoming);
incoming->mSize = ret;
nsRefPtr<SocketReceiveTask> t =
new SocketReceiveTask(this, incoming.forget());
NS_DispatchToMainThread(t);
// If ret is less than MAX_READ_SIZE, there's no more data in the socket
// for us to read now.
// If ret is less than MAX_READ_SIZE, there's no
// more data in the socket for us to read now.
if (ret < ssize_t(MAX_READ_SIZE)) {
return;
}

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

@ -42,25 +42,34 @@ union sockaddr_any {
class UnixSocketRawData
{
public:
nsAutoArrayPtr<uint8_t> mData;
// Number of octets in mData.
size_t mSize;
size_t mCurrentWriteOffset;
nsAutoArrayPtr<uint8_t> mData;
/**
* Constructor for situations where size is known beforehand (for example,
* when being assigned strings)
*
* Constructor for situations where only size is known beforehand
* (for example, when being assigned strings)
*/
UnixSocketRawData(int aSize) :
UnixSocketRawData(size_t aSize) :
mSize(aSize),
mCurrentWriteOffset(0)
{
mData = new uint8_t[aSize];
mData = new uint8_t[mSize];
}
/**
* Constructor for situations where size and data is known
* beforehand (for example, when being assigned strings)
*/
UnixSocketRawData(const void* aData, size_t aSize)
: mSize(aSize),
mCurrentWriteOffset(0)
{
MOZ_ASSERT(aData || !mSize);
mData = new uint8_t[mSize];
memcpy(mData, aData, mSize);
}
private:
UnixSocketRawData() {}
};
class UnixSocketImpl;
@ -92,13 +101,13 @@ public:
*/
virtual int Create() = 0;
/**
/**
* Since most socket specifics are related to address formation into a
* sockaddr struct, this function is defined by subclasses and fills in the
* structure as needed for whatever connection it is trying to build
*
* @param aIsServer True is we are acting as a server socket
* @param aAddrSize Size of the struct
* @param aAddrSize Size of the struct
* @param aAddr Struct to fill
* @param aAddress If aIsServer is false, Address to connect to. nullptr otherwise.
*
@ -109,7 +118,7 @@ public:
sockaddr_any& aAddr,
const char* aAddress) = 0;
/**
/**
* Does any socket type specific setup that may be needed
*
* @param aFd File descriptor for opened socket
@ -118,7 +127,7 @@ public:
*/
virtual bool SetUp(int aFd) = 0;
/**
/**
* Get address of socket we're currently connected to. Return null string if
* not connected.
*
@ -192,7 +201,7 @@ public:
const char* aAddress,
int aDelayMs = 0);
/**
/**
* Starts a task on the socket that will try to accept a new connection in a
* non-blocking manner.
*
@ -208,33 +217,33 @@ public:
*/
void CloseSocket();
/**
/**
* Callback for socket connect/accept success. Called after connect/accept has
* finished. Will be run on main thread, before any reads take place.
*/
virtual void OnConnectSuccess() = 0;
/**
/**
* Callback for socket connect/accept error. Will be run on main thread.
*/
virtual void OnConnectError() = 0;
/**
/**
* Callback for socket disconnect. Will be run on main thread.
*/
virtual void OnDisconnect() = 0;
/**
/**
* Called by implementation to notify consumer of success.
*/
void NotifySuccess();
/**
/**
* Called by implementation to notify consumer of error.
*/
void NotifyError();
/**
/**
* Called by implementation to notify consumer of disconnect.
*/
void NotifyDisconnect();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше