зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central and b2g-inbound
This commit is contained in:
Коммит
1717198314
|
@ -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 <br>boy!</p>
|
||||
<p id="case4">Hello <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;
|
||||
}
|
||||
|
||||
HandleSinkStateChanged(StatusStringToSinkState(value.get_nsString()));
|
||||
} else {
|
||||
NS_WARNING("Unknown sink property");
|
||||
// case 3: Successfully connected
|
||||
MOZ_ASSERT(prevState == SinkState::SINK_CONNECTING);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,20 +27,20 @@ public:
|
|||
* 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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче