diff --git a/accessible/jsat/ContentControl.jsm b/accessible/jsat/ContentControl.jsm
index 741da1fb2bd9..96b0bb005c4a 100644
--- a/accessible/jsat/ContentControl.jsm
+++ b/accessible/jsat/ContentControl.jsm
@@ -425,7 +425,12 @@ this.ContentControl.prototype = {
let sentToChild = this.sendToChild(vc, {
name: 'AccessFu:AutoMove',
- json: aOptions
+ json: {
+ moveMethod: aOptions.moveMethod,
+ moveToFocused: aOptions.moveToFocused,
+ noOpIfOnScreen: true,
+ forcePresent: true
+ }
});
if (!moved && !sentToChild) {
diff --git a/accessible/jsat/EventManager.jsm b/accessible/jsat/EventManager.jsm
index f93932e8d991..c4d6fe52469b 100644
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -279,8 +279,10 @@ this.EventManager.prototype = {
// Put vc where the focus is at
let acc = aEvent.accessible;
let doc = aEvent.accessibleDocument;
- if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) {
- this.contentControl.autoMove(acc);
+ if ([Roles.CHROME_WINDOW,
+ Roles.DOCUMENT,
+ Roles.APPLICATION].indexOf(acc.role) < 0) {
+ this.contentControl.autoMove(acc);
}
break;
}
diff --git a/accessible/jsat/Gestures.jsm b/accessible/jsat/Gestures.jsm
index cecd40b648a1..3d2fd2fde982 100644
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -228,7 +228,7 @@ this.GestureTracker = { // jshint ignore:line
* @param {Number} aTimeStamp A new pointer event timeStamp.
*/
handle: function GestureTracker_handle(aDetail, aTimeStamp) {
- Logger.debug(() => {
+ Logger.gesture(() => {
return ['Pointer event', aDetail.type, 'at:', aTimeStamp,
JSON.stringify(aDetail.points)];
});
@@ -332,7 +332,7 @@ function compileDetail(aType, aPoints, keyMap = {x: 'startX', y: 'startY'}) {
*/
function Gesture(aTimeStamp, aPoints = {}, aLastEvent = undefined) {
this.startTime = Date.now();
- Logger.debug('Creating', this.id, 'gesture.');
+ Logger.gesture('Creating', this.id, 'gesture.');
this.points = aPoints;
this.lastEvent = aLastEvent;
this._deferred = Promise.defer();
@@ -509,7 +509,7 @@ Gesture.prototype = {
if (this.isComplete) {
return;
}
- Logger.debug('Resolving', this.id, 'gesture.');
+ Logger.gesture('Resolving', this.id, 'gesture.');
this.isComplete = true;
let detail = this.compile();
if (detail) {
@@ -533,7 +533,7 @@ Gesture.prototype = {
if (this.isComplete) {
return;
}
- Logger.debug('Rejecting', this.id, 'gesture.');
+ Logger.gesture('Rejecting', this.id, 'gesture.');
this.isComplete = true;
return {
id: this.id,
diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm
index d7fc792578db..57ab6c5176d3 100644
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -473,11 +473,12 @@ State.prototype = {
};
this.Logger = { // jshint ignore:line
+ GESTURE: -1,
DEBUG: 0,
INFO: 1,
WARNING: 2,
ERROR: 3,
- _LEVEL_NAMES: ['DEBUG', 'INFO', 'WARNING', 'ERROR'],
+ _LEVEL_NAMES: ['GESTURE', 'DEBUG', 'INFO', 'WARNING', 'ERROR'],
logLevel: 1, // INFO;
@@ -490,7 +491,7 @@ this.Logger = { // jshint ignore:line
let args = Array.prototype.slice.call(arguments, 1);
let message = (typeof(args[0]) === 'function' ? args[0]() : args).join(' ');
- message = '[' + Utils.ScriptName + '] ' + this._LEVEL_NAMES[aLogLevel] +
+ message = '[' + Utils.ScriptName + '] ' + this._LEVEL_NAMES[aLogLevel + 1] +
' ' + message + '\n';
dump(message);
// Note: used for testing purposes. If |this.test| is true, also log to
@@ -509,6 +510,11 @@ this.Logger = { // jshint ignore:line
this, [this.INFO].concat(Array.prototype.slice.call(arguments)));
},
+ gesture: function gesture() {
+ this.log.apply(
+ this, [this.GESTURE].concat(Array.prototype.slice.call(arguments)));
+ },
+
debug: function debug() {
this.log.apply(
this, [this.DEBUG].concat(Array.prototype.slice.call(arguments)));
@@ -552,14 +558,16 @@ this.Logger = { // jshint ignore:line
},
accessibleToString: function accessibleToString(aAccessible) {
- let str = '[ defunct ]';
- try {
- str = '[ ' + Utils.AccRetrieval.getStringRole(aAccessible.role) +
- ' | ' + aAccessible.name + ' ]';
- } catch (x) {
+ if (!aAccessible) {
+ return '[ null ]';
}
- return str;
+ try {
+ return'[ ' + Utils.AccRetrieval.getStringRole(aAccessible.role) +
+ ' | ' + aAccessible.name + ' ]';
+ } catch (x) {
+ return '[ defunct ]';
+ }
},
eventToString: function eventToString(aEvent) {
diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js
index 97c566bb9fe4..0f97929460a6 100644
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -255,7 +255,7 @@ AccessFuContentTest.prototype = {
this.currentPair = this.queue.shift();
if (this.currentPair) {
- if (this.currentPair[0] instanceof Function) {
+ if (typeof this.currentPair[0] === 'function') {
this.currentPair[0](this.mms[0]);
} else if (this.currentPair[0]) {
this.mms[0].sendAsyncMessage(this.currentPair[0].name,
@@ -290,7 +290,11 @@ AccessFuContentTest.prototype = {
if (expected.speak) {
var checkFunc = SimpleTest[expected.speak_checkFunc] || isDeeply;
checkFunc.apply(SimpleTest, [speech, expected.speak,
- '"' + JSON.stringify(speech) + '" spoken']);
+ 'spoken: ' + JSON.stringify(speech) +
+ ' expected: ' + JSON.stringify(expected.speak) +
+ ' after: ' + (typeof this.currentPair[0] === 'function' ?
+ this.currentPair[0].toString() :
+ JSON.stringify(this.currentPair[0]))]);
}
if (expected.android) {
diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html
index 5bbac658c195..14f7a4a62570 100644
--- a/accessible/tests/mochitest/jsat/test_content_integration.html
+++ b/accessible/tests/mochitest/jsat/test_content_integration.html
@@ -136,8 +136,8 @@
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
}],
[ContentMessages.focusSelector('button#home', false), {
- speak: ['Home button']
- }]
+ speak: ['Home', {'string': 'pushbutton'}]
+ }],
// Blur button and reset cursor
[ContentMessages.focusSelector('button#home', true), null],
@@ -152,13 +152,13 @@
speak: ['Phone status bar', 'Traversal Rule test document']
}],
[doc.defaultView.showAlert, {
- speak: ['This is an alert! heading level 1 dialog']
+ speak: ['This is an alert!',
+ {'string': 'headingLevel', 'args': [1]},
+ {'string': 'dialog'}]
}],
- [function() {
- doc.defaultView.hideAlert()
- }, {
- speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
+ [doc.defaultView.hideAlert, {
+ speak: ["wow", {"string": "headingLevel","args": [1]}, "such app"],
}],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
@@ -171,12 +171,14 @@
speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app']
}],
[doc.defaultView.showAlert, {
- speak: ['This is an alert! heading level 1 dialog']
+ speak: ['This is an alert!',
+ {'string': 'headingLevel', 'args': [1]},
+ {'string': 'dialog'}]
}],
// XXX: Place cursor back where it was.
[doc.defaultView.hideAlert, {
- speak: ['many option not checked check button such app']
+ speak: ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'],
}],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
@@ -186,7 +188,9 @@
speak: ['Phone status bar', 'Traversal Rule test document']
}],
[doc.defaultView.showAlert, {
- speak: ['This is an alert! heading level 1 dialog']
+ speak: ['This is an alert!',
+ {'string': 'headingLevel', 'args': [1]},
+ {'string': 'dialog'}]
}],
[function() {
diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js
index 885e38f7115a..6341b26b580c 100644
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -522,8 +522,8 @@ var shell = {
// based on tab's coordinate. So get the actual offsets between shell and evt.target.
let elt = evt.target;
let win = elt.ownerDocument.defaultView;
- let offsetX = win.mozInnerScreenX;
- let offsetY = win.mozInnerScreenY;
+ let offsetX = win.mozInnerScreenX - window.mozInnerScreenX;
+ let offsetY = win.mozInnerScreenY - window.mozInnerScreenY;
let rect = elt.getBoundingClientRect();
offsetX += rect.left;
diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index 3a4f590e65c1..7df0ca77ae71 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,13 +19,13 @@
-
+
-
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index d9f07e68f6db..b9babb11b9cf 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,10 +17,10 @@
-
+
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index ce0d311ed4d2..4a12dcff25a8 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index 3a4f590e65c1..7df0ca77ae71 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,13 +19,13 @@
-
+
-
+
diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml
index adf020c02175..c858bc45d90f 100644
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -17,10 +17,10 @@
-
+
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index a0ce63d4cb4f..00ee864ac91a 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
- "revision": "2fb6119da922ebdab70c79e7f515f49fa582b2c5",
+ "revision": "a5d998cfe7cd004c7967e40efaaad0ccb829ecc4",
"repo_path": "/integration/gaia-central"
}
diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml
index 9ba977901cd1..a8b5d1703430 100644
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -17,12 +17,12 @@
-
+
-
+
diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml
index 814bba4a6cbe..27153a46f257 100644
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index a1ce7155d5de..03d8a9eb2c98 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,10 +17,10 @@
-
+
-
+
diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml
index ce0fbfcb823b..cc3d0197d66a 100644
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -17,12 +17,12 @@
-
+
-
+
diff --git a/b2g/confvars.sh b/b2g/confvars.sh
index 98ef5283328a..e45d482220f7 100644
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -23,7 +23,7 @@ MOZ_SERVICES_METRICS=1
MOZ_CAPTIVEDETECT=1
MOZ_WEBSMS_BACKEND=1
-MOZ_DISABLE_CRYPTOLEGACY=1
+MOZ_NO_SMART_CARDS=1
MOZ_APP_STATIC_INI=1
NSS_NO_LIBPKIX=1
NSS_DISABLE_DBM=1
diff --git a/browser/themes/shared/devtools/webconsole.inc.css b/browser/themes/shared/devtools/webconsole.inc.css
index aa49039dfd75..f471a4e87467 100644
--- a/browser/themes/shared/devtools/webconsole.inc.css
+++ b/browser/themes/shared/devtools/webconsole.inc.css
@@ -17,24 +17,24 @@ a {
.message {
display: flex;
- flex: 0 0 main-size;
+ flex: none;
padding: 0 7px;
width: 100%;
box-sizing: border-box;
}
.message > .timestamp {
- flex: 0 0 main-size;
+ flex: none;
color: GrayText;
margin: 4px 6px 0 0;
}
.message > .indent {
- flex: 0 0 main-size;
+ flex: none;
}
.message > .icon {
- flex: 0 0 main-size;
+ flex: none;
margin: 3px 6px 0 0;
padding: 0 4px;
height: 1em;
@@ -66,7 +66,7 @@ a {
/* The red bubble that shows the number of times a message is repeated */
.message-repeats {
-moz-user-select: none;
- flex: 0 0 main-size;
+ flex: none;
margin: 2px 6px;
padding: 0 6px;
height: 1.25em;
@@ -84,7 +84,7 @@ a {
.message-location {
display: flex;
- flex: 0 0 main-size;
+ flex: none;
align-self: flex-start;
justify-content: flex-end;
width: 10em;
@@ -106,7 +106,7 @@ a {
}
.message-location > .line-number {
- flex: 0 0 main-size;
+ flex: none;
}
.message-flex-body {
@@ -236,7 +236,7 @@ a {
}
.message[category=network] .method {
- flex: 0 0 main-size;
+ flex: none;
}
.message[category=network]:not(.navigation-marker) .url {
@@ -250,7 +250,7 @@ a {
}
.message[category=network] .status {
- flex: 0 0 main-size;
+ flex: none;
-moz-margin-start: 6px;
}
diff --git a/build/autoconf/icu.m4 b/build/autoconf/icu.m4
index f7417d8f096a..df7f5edf3efd 100644
--- a/build/autoconf/icu.m4
+++ b/build/autoconf/icu.m4
@@ -180,7 +180,7 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
# --with-cross-build requires absolute path
ICU_HOST_PATH=`cd $_objdir/intl/icu/host && pwd`
- ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH"
+ ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH --disable-tools"
ICU_TARGET_OPT="--build=$build --host=$target"
else
# CROSS_COMPILE isn't set build and target are i386 and x86-64.
diff --git a/build/macosx/universal/unify b/build/macosx/universal/unify
index 82b24560f411..38dd354145a0 100755
--- a/build/macosx/universal/unify
+++ b/build/macosx/universal/unify
@@ -1395,7 +1395,7 @@ sub readZipCRCs($) {
if ($$this{'magicInit'}) {
if (defined($$this{'magicErrno'})) {
if (defined($$this{'magicErrMsg'})) {
- complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+ main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
$$this{'path'});
}
$! = $$this{'magicErrno'};
@@ -1409,7 +1409,7 @@ sub readZipCRCs($) {
if (!sysopen($fh, $$this{'path'}, O_RDONLY)) {
$$this{'magicErrno'} = $!;
$$this{'magicErrMsg'} = 'open "'.$$this{'path'}.'": '.$!;
- complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+ main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
$$this{'path'});
return undef;
}
@@ -1419,7 +1419,7 @@ sub readZipCRCs($) {
if (!defined($bytes = sysread($fh, $magic, 4))) {
$$this{'magicErrno'} = $!;
$$this{'magicErrMsg'} = 'read "'.$$this{'path'}.'": '.$!;
- complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+ main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
$$this{'path'});
close($fh);
return undef;
diff --git a/config/external/nss/crmf/moz.build b/config/external/nss/crmf/moz.build
index 3f51ab5f1a61..d0ceb4bd9cf4 100644
--- a/config/external/nss/crmf/moz.build
+++ b/config/external/nss/crmf/moz.build
@@ -8,7 +8,7 @@ LIBRARY_NAME = 'crmf'
if CONFIG['MOZ_NATIVE_NSS']:
OS_LIBS += [l for l in CONFIG['NSS_LIBS'] if l.startswith('-L')]
- OS_LIBS += '-lcrmf'
+ OS_LIBS += ['-lcrmf']
else:
USE_LIBS += [
# The dependency on nss is not real, but is required to force the
diff --git a/configure.in b/configure.in
index 7cbc077b5cb4..cd0e29e469ec 100644
--- a/configure.in
+++ b/configure.in
@@ -1992,7 +1992,10 @@ ia64*-hpux*)
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
MOZ_GFX_OPTIMIZE_MOBILE=1
- MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions"
+ MOZ_OPTIMIZE_FLAGS="-Os -fno-reorder-functions"
+ if test -z "$CLANG_CC"; then
+ MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS"
+ fi
;;
*-*linux*)
@@ -2009,7 +2012,10 @@ ia64*-hpux*)
MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50"
esac
MOZ_PGO_OPTIMIZE_FLAGS="-O3"
- MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK"
+ MOZ_OPTIMIZE_FLAGS="-Os $MOZ_OPTIMIZE_SIZE_TWEAK"
+ if test -z "$CLANG_CC"; then
+ MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS"
+ fi
fi
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
@@ -3779,7 +3785,7 @@ MOZ_WMF=
if test -n "$MOZ_FMP4"; then
MOZ_FMP4=1
else
- MOZ_FMP4 =
+ MOZ_FMP4=
fi
MOZ_EME=1
MOZ_FFMPEG=
@@ -3826,7 +3832,7 @@ MOZ_XUL=1
MOZ_ZIPWRITER=1
NS_PRINTING=1
MOZ_PDF_PRINTING=
-MOZ_DISABLE_CRYPTOLEGACY=
+MOZ_NO_SMART_CARDS=
NSS_DISABLE_DBM=
NECKO_COOKIES=1
NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device"
@@ -6342,12 +6348,12 @@ fi
AC_SUBST(MOZ_DISABLE_PARENTAL_CONTROLS)
dnl ========================================================
-dnl = Disable DOMCrypto
+dnl = Disable smartcard support
dnl ========================================================
-if test -n "$MOZ_DISABLE_CRYPTOLEGACY"; then
- AC_DEFINE(MOZ_DISABLE_CRYPTOLEGACY)
+if test -n "$MOZ_NO_SMART_CARDS"; then
+ AC_DEFINE(MOZ_NO_SMART_CARDS)
fi
-AC_SUBST(MOZ_DISABLE_CRYPTOLEGACY)
+AC_SUBST(MOZ_NO_SMART_CARDS)
dnl ========================================================
dnl = Disable EV certificate verification
diff --git a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html b/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html
deleted file mode 100644
index a6b62d582183..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- CSP eval script tests
-
-
-
-
- Foo.
-
-
-
diff --git a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html^headers^ b/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html^headers^
deleted file mode 100644
index 0cb5288bec4e..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.html^headers^
+++ /dev/null
@@ -1,2 +0,0 @@
-Cache-Control: no-cache
-Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-eval'
diff --git a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.js b/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.js
deleted file mode 100644
index dbcc66cb21c7..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_allowed_getCRMFRequest.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// some javascript for the CSP eval() tests
-// all of these evals should succeed, as the document loading this script
-// has script-src 'self' 'unsafe-eval'
-
-function logResult(str, passed) {
- var elt = document.createElement('div');
- var color = passed ? "#cfc;" : "#fcc";
- elt.setAttribute('style', 'background-color:' + color + '; width:100%; border:1px solid black; padding:3px; margin:4px;');
- elt.innerHTML = str;
- document.body.appendChild(elt);
-}
-
-// callback for when stuff is allowed by CSP
-var onevalexecuted = (function(window) {
- return function(shouldrun, what, data) {
- window.parent.scriptRan(shouldrun, what, data);
- logResult((shouldrun ? "PASS: " : "FAIL: ") + what + " : " + data, shouldrun);
- };})(window);
-
-// callback for when stuff is blocked
-var onevalblocked = (function(window) {
- return function(shouldrun, what, data) {
- window.parent.scriptBlocked(shouldrun, what, data);
- logResult((shouldrun ? "FAIL: " : "PASS: ") + what + " : " + data, !shouldrun);
- };})(window);
-
-
-// Defer until document is loaded so that we can write the pretty result boxes
-// out.
-addEventListener('load', function() {
- // test that allows crypto.generateCRMFRequest eval to run
- try {
- var script =
- 'console.log("dynamic script passed to crypto.generateCRMFRequest should execute")';
- crypto.generateCRMFRequest('CN=0', 0, 0, null, script, 384, null, 'rsa-dual-use');
- onevalexecuted(true, "eval(script) inside crypto.generateCRMFRequest",
- "eval executed during crypto.generateCRMFRequest");
- } catch (e) {
- onevalblocked(true, "eval(script) inside crypto.generateCRMFRequest",
- "eval was blocked during crypto.generateCRMFRequest");
- }
-}, false);
diff --git a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html b/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html
deleted file mode 100644
index 7b122389be54..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- CSP eval script tests
-
-
-
-
- Foo.
-
-
-
diff --git a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html^headers^ b/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html^headers^
deleted file mode 100644
index b91ba384d948..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.html^headers^
+++ /dev/null
@@ -1,2 +0,0 @@
-Cache-Control: no-cache
-Content-Security-Policy: default-src 'self'
diff --git a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.js b/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.js
deleted file mode 100644
index 90826e3bc9de..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_main_getCRMFRequest.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// some javascript for the CSP eval() tests
-
-function logResult(str, passed) {
- var elt = document.createElement('div');
- var color = passed ? "#cfc;" : "#fcc";
- elt.setAttribute('style', 'background-color:' + color + '; width:100%; border:1px solid black; padding:3px; margin:4px;');
- elt.innerHTML = str;
- document.body.appendChild(elt);
-}
-
-window._testResults = {};
-
-// callback for when stuff is allowed by CSP
-var onevalexecuted = (function(window) {
- return function(shouldrun, what, data) {
- window._testResults[what] = "ran";
- window.parent.scriptRan(shouldrun, what, data);
- logResult((shouldrun ? "PASS: " : "FAIL: ") + what + " : " + data, shouldrun);
- };})(window);
-
-// callback for when stuff is blocked
-var onevalblocked = (function(window) {
- return function(shouldrun, what, data) {
- window._testResults[what] = "blocked";
- window.parent.scriptBlocked(shouldrun, what, data);
- logResult((shouldrun ? "FAIL: " : "PASS: ") + what + " : " + data, !shouldrun);
- };})(window);
-
-
-// Defer until document is loaded so that we can write the pretty result boxes
-// out.
-addEventListener('load', function() {
- // generateCRMFRequest test -- make sure we cannot eval the callback if CSP is in effect
- try {
- var script = 'console.log("dynamic script eval\'d in crypto.generateCRMFRequest should be disallowed")';
- crypto.generateCRMFRequest('CN=0', 0, 0, null, script, 384, null, 'rsa-dual-use');
- onevalexecuted(false, "crypto.generateCRMFRequest()",
- "crypto.generateCRMFRequest() should not run!");
- } catch (e) {
- onevalblocked(false, "eval(script) inside crypto.generateCRMFRequest",
- "eval was blocked during crypto.generateCRMFRequest");
- }
-
-
-}, false);
-
-
-
diff --git a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html b/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html
deleted file mode 100644
index d36aeaaf1064..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- CSP eval script tests: no CSP specified
-
-
-
-
- Foo. See bug 824652
-
-
-
diff --git a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html^headers^ b/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html^headers^
deleted file mode 100644
index 9e23c73b7ffb..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.html^headers^
+++ /dev/null
@@ -1 +0,0 @@
-Cache-Control: no-cache
diff --git a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.js b/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.js
deleted file mode 100644
index 520491fb8ef7..000000000000
--- a/content/base/test/csp/file_CSP_evalscript_no_CSP_at_all.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// some javascript for the CSP eval() tests
-// all of these evals should succeed, as the document loading this script
-// has script-src 'self' 'unsafe-eval'
-
-function logResult(str, passed) {
- var elt = document.createElement('div');
- var color = passed ? "#cfc;" : "#fcc";
- elt.setAttribute('style', 'background-color:' + color + '; width:100%; border:1px solid black; padding:3px; margin:4px;');
- elt.innerHTML = str;
- document.body.appendChild(elt);
-}
-
-// callback for when stuff is allowed by CSP
-var onevalexecuted = (function(window) {
- return function(shouldrun, what, data) {
- window.parent.scriptRan(shouldrun, what, data);
- logResult((shouldrun ? "PASS: " : "FAIL: ") + what + " : " + data, shouldrun);
- };})(window);
-
-// callback for when stuff is blocked
-var onevalblocked = (function(window) {
- return function(shouldrun, what, data) {
- window.parent.scriptBlocked(shouldrun, what, data);
- logResult((shouldrun ? "FAIL: " : "PASS: ") + what + " : " + data, !shouldrun);
- };})(window);
-
-
-// Defer until document is loaded so that we can write the pretty result boxes
-// out.
-addEventListener('load', function() {
- // test that allows crypto.generateCRMFRequest eval to run when there is no CSP at all in place
- try {
- var script =
- 'console.log("dynamic script passed to crypto.generateCRMFRequest should execute")';
- crypto.generateCRMFRequest('CN=0', 0, 0, null, script, 384, null, 'rsa-dual-use');
- onevalexecuted(true, "eval(script) inside crypto.generateCRMFRequest: no CSP at all",
- "eval executed during crypto.generateCRMFRequest where no CSP is set at all");
- } catch (e) {
- onevalblocked(true, "eval(script) inside crypto.generateCRMFRequest",
- "eval was blocked during crypto.generateCRMFRequest");
- }
-}, false);
diff --git a/content/base/test/csp/mochitest.ini b/content/base/test/csp/mochitest.ini
index e3eaa4221b3f..12733d57aa69 100644
--- a/content/base/test/csp/mochitest.ini
+++ b/content/base/test/csp/mochitest.ini
@@ -20,19 +20,10 @@ support-files =
file_CSP_bug888172.sjs
file_CSP_evalscript_main.js
file_CSP_evalscript_main_allowed.js
- file_CSP_evalscript_main_allowed_getCRMFRequest.js
- file_CSP_evalscript_main_getCRMFRequest.js
file_CSP_evalscript_main.html
file_CSP_evalscript_main.html^headers^
file_CSP_evalscript_main_allowed.html
file_CSP_evalscript_main_allowed.html^headers^
- file_CSP_evalscript_main_allowed_getCRMFRequest.html
- file_CSP_evalscript_main_allowed_getCRMFRequest.html^headers^
- file_CSP_evalscript_main_getCRMFRequest.html
- file_CSP_evalscript_main_getCRMFRequest.html^headers^
- file_CSP_evalscript_no_CSP_at_all.html
- file_CSP_evalscript_no_CSP_at_all.html^headers^
- file_CSP_evalscript_no_CSP_at_all.js
file_CSP_frameancestors_main.html
file_CSP_frameancestors_main.js
file_CSP_frameancestors.sjs
@@ -112,8 +103,6 @@ support-files =
[test_CSP_bug885433.html]
[test_CSP_bug888172.html]
[test_CSP_evalscript.html]
-[test_CSP_evalscript_getCRMFRequest.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # no (deprecated) window.crypto support in multiprocess (bug 824652)
[test_CSP_frameancestors.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' # Times out, not sure why (bug 1008445)
[test_CSP_inlinescript.html]
diff --git a/content/base/test/csp/test_CSP_evalscript_getCRMFRequest.html b/content/base/test/csp/test_CSP_evalscript_getCRMFRequest.html
deleted file mode 100644
index fa1f648a2561..000000000000
--- a/content/base/test/csp/test_CSP_evalscript_getCRMFRequest.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
- Test for Content Security Policy "no eval" in crypto.getCRMFRequest()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/content/media/AudioStream.cpp b/content/media/AudioStream.cpp
index 04c160c5ff5a..02a5282a9953 100644
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -17,6 +17,7 @@
#include "mozilla/Telemetry.h"
#include "soundtouch/SoundTouch.h"
#include "Latency.h"
+#include "nsPrintfCString.h"
#ifdef XP_MACOSX
#include
#endif
@@ -254,6 +255,7 @@ AudioStream::AudioStream()
, mState(INITIALIZED)
, mNeedsStart(false)
, mShouldDropFrames(false)
+ , mPendingAudioInitTask(false)
{
// keep a ref in case we shut down later than nsLayoutStatics
mLatencyLog = AsyncLatencyLogger::Get(true);
@@ -535,19 +537,24 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
// cause us to move from INITIALIZED to RUNNING. Until then, we
// can't access any cubeb functions.
// Use a RefPtr to avoid leaks if Dispatch fails
+ mPendingAudioInitTask = true;
RefPtr init = new AudioInitTask(this, aLatencyRequest, params);
- init->Dispatch();
- return NS_OK;
+ nsresult rv = init->Dispatch();
+ if (NS_FAILED(rv)) {
+ mPendingAudioInitTask = false;
+ }
+ return rv;
}
// High latency - open synchronously
nsresult rv = OpenCubeb(params, aLatencyRequest);
+ NS_ENSURE_SUCCESS(rv, rv);
// See if we need to start() the stream, since we must do that from this
// thread for now (cubeb API issue)
{
MonitorAutoLock mon(mMonitor);
CheckForStart();
}
- return rv;
+ return NS_OK;
}
// On certain MacBookPro, the microphone is located near the left speaker.
@@ -627,15 +634,9 @@ nsresult
AudioStream::OpenCubeb(cubeb_stream_params &aParams,
LatencyRequest aLatencyRequest)
{
- {
- MonitorAutoLock mon(mMonitor);
- if (mState == AudioStream::SHUTDOWN) {
- return NS_ERROR_FAILURE;
- }
- }
-
cubeb* cubebContext = GetCubebContext();
if (!cubebContext) {
+ NS_WARNING("Can't get cubeb context!");
MonitorAutoLock mon(mMonitor);
mState = AudioStream::ERRORED;
return NS_ERROR_FAILURE;
@@ -658,21 +659,15 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
if (cubeb_stream_init(cubebContext, &stream, "AudioStream", aParams,
latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
MonitorAutoLock mon(mMonitor);
+ MOZ_ASSERT(mState != SHUTDOWN);
mCubebStream.own(stream);
- // Make sure we weren't shut down while in flight!
- if (mState == SHUTDOWN) {
- mCubebStream.reset();
- LOG(("AudioStream::OpenCubeb() %p Shutdown while opening cubeb", this));
- return NS_ERROR_FAILURE;
- }
-
// We can't cubeb_stream_start() the thread from a transient thread due to
// cubeb API requirements (init can be called from another thread, but
// not start/stop/destroy/etc)
} else {
MonitorAutoLock mon(mMonitor);
mState = ERRORED;
- LOG(("AudioStream::OpenCubeb() %p failed to init cubeb", this));
+ NS_WARNING(nsPrintfCString("AudioStream::OpenCubeb() %p failed to init cubeb", this).get());
return NS_ERROR_FAILURE;
}
}
@@ -693,6 +688,14 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
return NS_OK;
}
+void
+AudioStream::AudioInitTaskFinished()
+{
+ MonitorAutoLock mon(mMonitor);
+ mPendingAudioInitTask = false;
+ mon.NotifyAll();
+}
+
void
AudioStream::CheckForStart()
{
@@ -731,6 +734,7 @@ AudioInitTask::Run()
}
nsresult rv = mAudioStream->OpenCubeb(mParams, mLatencyRequest);
+ mAudioStream->AudioInitTaskFinished();
// and now kill this thread
NS_DispatchToMainThread(this);
@@ -951,6 +955,10 @@ AudioStream::Shutdown()
MonitorAutoLock mon(mMonitor);
LOG(("AudioStream: Shutdown %p, state %d", this, mState));
+ while (mPendingAudioInitTask) {
+ mon.Wait();
+ }
+
if (mCubebStream) {
MonitorAutoUnlock mon(mMonitor);
// Force stop to put the cubeb stream in a stable state before deletion.
diff --git a/content/media/AudioStream.h b/content/media/AudioStream.h
index c2914b2f7425..927a5438ddb3 100644
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -299,6 +299,7 @@ private:
// So we can call it asynchronously from AudioInitTask
nsresult OpenCubeb(cubeb_stream_params &aParams,
LatencyRequest aLatencyRequest);
+ void AudioInitTaskFinished();
void CheckForStart();
@@ -425,6 +426,9 @@ private:
// is not going to be called for a little while, simply drop incoming frames.
// This is only on OSX for now, because other systems handle this gracefully.
bool mShouldDropFrames;
+ // True if there is a pending AudioInitTask. Shutdown() will wait until the
+ // pending AudioInitTask is finished.
+ bool mPendingAudioInitTask;
// This mutex protects the static members below.
static StaticMutex sMutex;
diff --git a/dom/base/Crypto.cpp b/dom/base/Crypto.cpp
index ddff2aea59b8..52cfb880936c 100644
--- a/dom/base/Crypto.cpp
+++ b/dom/base/Crypto.cpp
@@ -127,82 +127,6 @@ Crypto::Subtle()
return mSubtle;
}
-#ifndef MOZ_DISABLE_CRYPTOLEGACY
-// Stub out the legacy nsIDOMCrypto methods. The actual
-// implementations are in security/manager/ssl/src/nsCrypto.{cpp,h}
-
-NS_IMETHODIMP
-Crypto::GetEnableSmartCardEvents(bool *aEnableSmartCardEvents)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::SetEnableSmartCardEvents(bool aEnableSmartCardEvents)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-bool
-Crypto::EnableSmartCardEvents()
-{
- return false;
-}
-
-void
-Crypto::SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv)
-{
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-}
-
-void
-Crypto::GetVersion(nsString& aVersion)
-{
-}
-
-mozilla::dom::CRMFObject*
-Crypto::GenerateCRMFRequest(JSContext* aContext,
- const nsCString& aReqDN,
- const nsCString& aRegToken,
- const nsCString& aAuthenticator,
- const nsCString& aEaCert,
- const nsCString& aJsCallback,
- const Sequence& aArgs,
- ErrorResult& aRv)
-{
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
- return nullptr;
-}
-
-void
-Crypto::ImportUserCertificates(const nsAString& aNickname,
- const nsAString& aCmmfResponse,
- bool aDoForcedBackup,
- nsAString& aReturn,
- ErrorResult& aRv)
-{
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-}
-
-void
-Crypto::SignText(JSContext* aContext,
- const nsAString& aStringToSign,
- const nsAString& aCaOption,
- const Sequence& aArgs,
- nsAString& aReturn)
-
-{
- aReturn.AssignLiteral("error:internalError");
-}
-
-void
-Crypto::Logout(ErrorResult& aRv)
-{
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-}
-
-#endif
-
/* static */ uint8_t*
Crypto::GetRandomValues(uint32_t aLength)
{
diff --git a/dom/base/Crypto.h b/dom/base/Crypto.h
index dd2c204940bf..641e855453f8 100644
--- a/dom/base/Crypto.h
+++ b/dom/base/Crypto.h
@@ -4,17 +4,7 @@
#ifndef mozilla_dom_Crypto_h
#define mozilla_dom_Crypto_h
-#ifdef MOZ_DISABLE_CRYPTOLEGACY
#include "nsIDOMCrypto.h"
-#else
-#include "nsIDOMCryptoLegacy.h"
-namespace mozilla {
-namespace dom {
-class CRMFObject;
-}
-}
-#endif
-
#include "mozilla/dom/SubtleCrypto.h"
#include "nsPIDOMWindow.h"
@@ -51,38 +41,6 @@ public:
SubtleCrypto*
Subtle();
-#ifndef MOZ_DISABLE_CRYPTOLEGACY
- virtual bool EnableSmartCardEvents();
- virtual void SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv);
-
- virtual void GetVersion(nsString& aVersion);
-
- virtual mozilla::dom::CRMFObject*
- GenerateCRMFRequest(JSContext* aContext,
- const nsCString& aReqDN,
- const nsCString& aRegToken,
- const nsCString& aAuthenticator,
- const nsCString& aEaCert,
- const nsCString& aJsCallback,
- const Sequence& aArgs,
- ErrorResult& aRv);
-
- virtual void ImportUserCertificates(const nsAString& aNickname,
- const nsAString& aCmmfResponse,
- bool aDoForcedBackup,
- nsAString& aReturn,
- ErrorResult& aRv);
-
- virtual void SignText(JSContext* aContext,
- const nsAString& aStringToSign,
- const nsAString& aCaOption,
- const Sequence& aArgs,
- nsAString& aReturn);
-
- virtual void Logout(ErrorResult& aRv);
-
-#endif
-
// WebIDL
nsPIDOMWindow*
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 87dfd49a02f9..d3f6cd9ccea5 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -83,9 +83,6 @@
#include "nsIDocCharset.h"
#include "nsIDocument.h"
#include "Crypto.h"
-#ifndef MOZ_DISABLE_CRYPTOLEGACY
-#include "nsIDOMCryptoLegacy.h"
-#endif
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMEvent.h"
@@ -2364,14 +2361,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsCOMPtr oldDoc = mDoc;
-#ifndef MOZ_DISABLE_CRYPTOLEGACY
- // clear smartcard events, our document has gone away.
- if (mCrypto && XRE_GetProcessType() != GeckoProcessType_Content) {
- nsresult rv = mCrypto->SetEnableSmartCardEvents(false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-#endif
-
AutoJSAPI jsapi;
jsapi.Init();
JSContext *cx = jsapi.cx();
@@ -4459,20 +4448,7 @@ nsGlobalWindow::GetCrypto(ErrorResult& aError)
FORWARD_TO_INNER_OR_THROW(GetCrypto, (aError), aError, nullptr);
if (!mCrypto) {
-#ifndef MOZ_DISABLE_CRYPTOLEGACY
- if (XRE_GetProcessType() != GeckoProcessType_Content) {
- nsresult rv;
- mCrypto = do_CreateInstance(NS_CRYPTO_CONTRACTID, &rv);
- if (NS_FAILED(rv)) {
- aError.Throw(rv);
- return nullptr;
- }
- } else
-#endif
- {
- mCrypto = new Crypto();
- }
-
+ mCrypto = new Crypto();
mCrypto->Init(this);
}
return mCrypto;
diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
index fa49d1e9309e..06ebeb4482b0 100644
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -251,14 +251,7 @@ DOMInterfaces = {
'headerFile': 'nsGeoPosition.h'
},
-'CRMFObject': {
- 'headerFile': 'nsCrypto.h',
- 'nativeOwnership': 'owned',
- 'wrapperCache': False,
-},
-
'Crypto' : {
- 'implicitJSContext': [ 'generateCRMFRequest', 'signText' ],
'headerFile': 'Crypto.h'
},
diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h
index 85825f163022..a9ed3f475404 100644
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -146,6 +146,94 @@ enum BluetoothStatus {
STATUS_RMT_DEV_DOWN
};
+enum BluetoothBondState {
+ BOND_STATE_NONE,
+ BOND_STATE_BONDING,
+ BOND_STATE_BONDED
+};
+
+enum BluetoothDeviceType {
+ DEVICE_TYPE_BREDR,
+ DEVICE_TYPE_BLE,
+ DEVICE_TYPE_DUAL
+};
+
+enum BluetoothPropertyType {
+ PROPERTY_BDNAME,
+ PROPERTY_BDADDR,
+ PROPERTY_UUIDS,
+ PROPERTY_CLASS_OF_DEVICE,
+ PROPERTY_TYPE_OF_DEVICE,
+ PROPERTY_SERVICE_RECORD,
+ PROPERTY_ADAPTER_SCAN_MODE,
+ PROPERTY_ADAPTER_BONDED_DEVICES,
+ PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+ PROPERTY_REMOTE_FRIENDLY_NAME,
+ PROPERTY_REMOTE_RSSI,
+ PROPERTY_REMOTE_VERSION_INFO,
+ PROPERTY_REMOTE_DEVICE_TIMESTAMP
+};
+
+enum BluetoothScanMode {
+ SCAN_MODE_NONE,
+ SCAN_MODE_CONNECTABLE,
+ SCAN_MODE_CONNECTABLE_DISCOVERABLE
+};
+
+struct BluetoothUuid {
+ uint8_t mUuid[16];
+};
+
+struct BluetoothServiceRecord {
+ BluetoothUuid mUuid;
+ uint16_t mChannel;
+ char mName[256];
+};
+
+struct BluetoothRemoteInfo {
+ int mVerMajor;
+ int mVerMinor;
+ int mManufacturer;
+};
+
+struct BluetoothProperty {
+ /* Type */
+ BluetoothPropertyType mType;
+
+ /* Value
+ */
+
+ /* PROPERTY_BDNAME
+ PROPERTY_BDADDR
+ PROPERTY_REMOTE_FRIENDLY_NAME */
+ nsString mString;
+
+ /* PROPERTY_UUIDS */
+ nsTArray mUuidArray;
+
+ /* PROPERTY_ADAPTER_BONDED_DEVICES */
+ nsTArray mStringArray;
+
+ /* PROPERTY_CLASS_OF_DEVICE
+ PROPERTY_ADAPTER_DISCOVERY_TIMEOUT */
+ uint32_t mUint32;
+
+ /* PROPERTY_RSSI_VALUE */
+ int32_t mInt32;
+
+ /* PROPERTY_DEVICE_TYPE */
+ BluetoothDeviceType mDeviceType;
+
+ /* PROPERTY_SERVICE_RECORD */
+ BluetoothServiceRecord mServiceRecord;
+
+ /* PROPERTY_SCAN_MODE */
+ BluetoothScanMode mScanMode;
+
+ /* PROPERTY_REMOTE_VERSION_INFO */
+ BluetoothRemoteInfo mRemoteInfo;
+};
+
enum BluetoothSocketType {
RFCOMM = 1,
SCO = 2,
diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.cpp b/dom/bluetooth/bluedroid/BluetoothInterface.cpp
index e866659ba9e3..787c75de7bb1 100644
--- a/dom/bluetooth/bluedroid/BluetoothInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.cpp
@@ -23,6 +23,8 @@
out_
#endif
+#define MAX_UUID_SIZE 16
+
BEGIN_BLUETOOTH_NAMESPACE
template
@@ -92,6 +94,23 @@ Convert(bool aIn, bt_scan_mode_t& aOut)
return NS_OK;
}
+
+static nsresult
+Convert(bt_scan_mode_t aIn, BluetoothScanMode& aOut)
+{
+ static const BluetoothScanMode sScanMode[] = {
+ CONVERT(BT_SCAN_MODE_NONE, SCAN_MODE_NONE),
+ CONVERT(BT_SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE),
+ CONVERT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE,
+ SCAN_MODE_CONNECTABLE_DISCOVERABLE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sScanMode[aIn];
+ return NS_OK;
+}
+
struct ConvertNamedValue
{
ConvertNamedValue(const BluetoothNamedValue& aNamedValue)
@@ -173,6 +192,22 @@ Convert(const nsAString& aIn, bt_ssp_variant_t& aOut)
return NS_OK;
}
+static nsresult
+Convert(const bt_ssp_variant_t& aIn, nsAString& aOut)
+{
+ static const char * const sSspVariant[] = {
+ CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION, "PasskeyConfirmation"),
+ CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, "PasskeyEntry"),
+ CONVERT(BT_SSP_VARIANT_CONSENT, "Consent"),
+ CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION, "PasskeyNotification")
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = NS_ConvertUTF8toUTF16(sSspVariant[aIn]);
+ return NS_OK;
+}
+
static nsresult
Convert(const bool& aIn, uint8_t& aOut)
{
@@ -193,6 +228,18 @@ Convert(const uint8_t aIn[16], bt_uuid_t& aOut)
return NS_OK;
}
+static nsresult
+Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut)
+{
+ if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid));
+
+ return NS_OK;
+}
+
static nsresult
Convert(const nsAString& aIn, bt_pin_code_t& aOut)
{
@@ -241,6 +288,166 @@ Convert(const bt_bdaddr_t& aIn, nsAString& aOut)
return NS_OK;
}
+static nsresult
+Convert(const bt_bdaddr_t* aIn, nsAString& aOut)
+{
+ if (!aIn) {
+ aOut.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+ return NS_OK;
+ }
+ return Convert(*aIn, aOut);
+}
+
+static nsresult
+Convert(bt_state_t aIn, bool& aOut)
+{
+ static const bool sState[] = {
+ CONVERT(BT_STATE_OFF, false),
+ CONVERT(BT_STATE_ON, true)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sState[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(bt_property_type_t aIn, BluetoothPropertyType& aOut)
+{
+ static const BluetoothPropertyType sPropertyType[] = {
+ CONVERT(0, static_cast(0)), // invalid, required by gcc
+ CONVERT(BT_PROPERTY_BDNAME, PROPERTY_BDNAME),
+ CONVERT(BT_PROPERTY_BDADDR, PROPERTY_BDADDR),
+ CONVERT(BT_PROPERTY_UUIDS, PROPERTY_UUIDS),
+ CONVERT(BT_PROPERTY_CLASS_OF_DEVICE, PROPERTY_CLASS_OF_DEVICE),
+ CONVERT(BT_PROPERTY_TYPE_OF_DEVICE, PROPERTY_TYPE_OF_DEVICE),
+ CONVERT(BT_PROPERTY_SERVICE_RECORD, PROPERTY_SERVICE_RECORD),
+ CONVERT(BT_PROPERTY_ADAPTER_SCAN_MODE, PROPERTY_ADAPTER_SCAN_MODE),
+ CONVERT(BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+ PROPERTY_ADAPTER_BONDED_DEVICES),
+ CONVERT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+ PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
+ CONVERT(BT_PROPERTY_REMOTE_FRIENDLY_NAME, PROPERTY_REMOTE_FRIENDLY_NAME),
+ CONVERT(BT_PROPERTY_REMOTE_RSSI, PROPERTY_REMOTE_RSSI),
+ CONVERT(BT_PROPERTY_REMOTE_VERSION_INFO,PROPERTY_REMOTE_VERSION_INFO)
+ };
+ if (aIn == BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP) {
+ /* This case is handled separately to not populate
+ * |sPropertyType| with empty entries. */
+ aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP;
+ return NS_OK;
+ }
+ if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPropertyType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sPropertyType[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(bt_discovery_state_t aIn, bool& aOut)
+{
+ static const bool sDiscoveryState[] = {
+ CONVERT(BT_DISCOVERY_STOPPED, false),
+ CONVERT(BT_DISCOVERY_STARTED, true)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sDiscoveryState[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(const bt_bdname_t& aIn, nsAString& aOut)
+{
+ aOut = NS_ConvertUTF8toUTF16(reinterpret_cast(aIn.name));
+
+ return NS_OK;
+}
+
+static nsresult
+Convert(const bt_bdname_t* aIn, nsAString& aOut)
+{
+ if (!aIn) {
+ aOut.Truncate();
+ return NS_OK;
+ }
+ return Convert(*aIn, aOut);
+}
+
+static nsresult
+Convert(bt_bond_state_t aIn, BluetoothBondState& aOut)
+{
+ static const BluetoothBondState sBondState[] = {
+ CONVERT(BT_BOND_STATE_NONE, BOND_STATE_NONE),
+ CONVERT(BT_BOND_STATE_BONDING, BOND_STATE_BONDING),
+ CONVERT(BT_BOND_STATE_BONDED, BOND_STATE_BONDED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sBondState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sBondState[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(bt_acl_state_t aIn, bool& aOut)
+{
+ static const bool sAclState[] = {
+ CONVERT(BT_ACL_STATE_CONNECTED, true),
+ CONVERT(BT_ACL_STATE_DISCONNECTED, false)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sAclState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sAclState[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut)
+{
+ static const BluetoothDeviceType sDeviceType[] = {
+ CONVERT(0, static_cast(0)), // invalid, required by gcc
+ CONVERT(BT_DEVICE_DEVTYPE_BREDR, DEVICE_TYPE_BREDR),
+ CONVERT(BT_DEVICE_DEVTYPE_BLE, DEVICE_TYPE_BLE),
+ CONVERT(BT_DEVICE_DEVTYPE_DUAL, DEVICE_TYPE_DUAL)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sDeviceType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sDeviceType[aIn];
+ return NS_OK;
+}
+
+static nsresult
+Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut)
+{
+ aOut.mVerMajor = aIn.version;
+ aOut.mVerMinor = aIn.sub_ver;
+ aOut.mManufacturer = aIn.manufacturer;
+
+ return NS_OK;
+}
+
+static nsresult
+Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut)
+{
+ nsresult rv = Convert(aIn.uuid, aOut.mUuid);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ aOut.mChannel = aIn.channel;
+
+ MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName));
+ memcpy(aOut.mName, aIn.name, sizeof(aOut.mName));
+
+ return NS_OK;
+}
+
static nsresult
Convert(BluetoothSocketType aIn, btsock_type_t& aOut)
{
@@ -556,6 +763,101 @@ ConvertDefault(const Tin& aIn, const Tout& aDefault)
return out;
}
+/* This implementation of |Convert| is a helper for copying the
+ * input value into the output value. It handles all cases that
+ * need no conversion.
+ */
+template
+static nsresult
+Convert(const T& aIn, T& aOut)
+{
+ aOut = aIn;
+
+ return NS_OK;
+}
+
+static nsresult
+Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
+{
+ /* type conversion */
+
+ nsresult rv = Convert(aIn.type, aOut.mType);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ /* value conversion */
+
+ switch (aOut.mType) {
+ case PROPERTY_BDNAME:
+ /* fall through */
+ case PROPERTY_REMOTE_FRIENDLY_NAME:
+ {
+ // We construct an nsCString here because bdname
+ // returned from Bluedroid is not 0-terminated.
+ aOut.mString = NS_ConvertUTF8toUTF16(
+ nsCString(static_cast(aIn.val), aIn.len));
+ }
+ break;
+ case PROPERTY_BDADDR:
+ rv = Convert(*static_cast(aIn.val), aOut.mString);
+ break;
+ case PROPERTY_UUIDS:
+ {
+ size_t numUuids = aIn.len / MAX_UUID_SIZE;
+ ConvertArray array(
+ static_cast(aIn.val), numUuids);
+ aOut.mUuidArray.SetLength(numUuids);
+ rv = Convert(array, aOut.mUuidArray);
+ }
+ break;
+ case PROPERTY_CLASS_OF_DEVICE:
+ /* fall through */
+ case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ aOut.mUint32 = *static_cast(aIn.val);
+ break;
+ case PROPERTY_TYPE_OF_DEVICE:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mDeviceType);
+ break;
+ case PROPERTY_SERVICE_RECORD:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mServiceRecord);
+ break;
+ case PROPERTY_ADAPTER_SCAN_MODE:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mScanMode);
+ break;
+ case PROPERTY_ADAPTER_BONDED_DEVICES:
+ {
+ size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
+ ConvertArray array(
+ static_cast(aIn.val), numAddresses);
+ aOut.mStringArray.SetLength(numAddresses);
+ rv = Convert(array, aOut.mStringArray);
+ }
+ break;
+ case PROPERTY_REMOTE_RSSI:
+ aOut.mInt32 = *static_cast(aIn.val);
+ break;
+ case PROPERTY_REMOTE_VERSION_INFO:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mRemoteInfo);
+ break;
+ case PROPERTY_REMOTE_DEVICE_TIMESTAMP:
+ /* nothing to do */
+ break;
+ default:
+ /* mismatch with type conversion */
+ NS_NOTREACHED("Unhandled property type");
+ break;
+ }
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+}
+
//
// Result handling
//
@@ -646,6 +948,451 @@ private:
Tin3 mArg3;
};
+//
+// Notification handling
+//
+
+template
+class BluetoothNotificationRunnable1 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationRunnable1 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationRunnable1::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)(mArg1);
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationRunnable1(Res (ObjectType::*aMethod)(Arg1))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1);
+ Tin1 mArg1;
+};
+
+template
+class BluetoothNotificationRunnable2 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationRunnable2 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2),
+ const T1& aIn1, const T2& aIn2)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationRunnable2::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)(mArg1, mArg2);
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationRunnable2(Res (ObjectType::*aMethod)(Arg1, Arg2))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2);
+ Tin1 mArg1;
+ Tin2 mArg2;
+};
+
+template
+class BluetoothNotificationRunnable3 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationRunnable3 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationRunnable3::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)(mArg1, mArg2, mArg3);
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationRunnable3(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3);
+ Tin1 mArg1;
+ Tin2 mArg2;
+ Tin3 mArg3;
+};
+
+template
+class BluetoothNotificationRunnable4 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationRunnable4 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationRunnable4::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4);
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationRunnable4(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2,
+ const T3& aIn3, const T4& aIn4)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn4, mArg4);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4);
+ Tin1 mArg1;
+ Tin2 mArg2;
+ Tin3 mArg3;
+ Tin4 mArg4;
+};
+
+template
+class BluetoothNotificationRunnable5 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationRunnable5 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsRefPtr runnable = Create(aMethod,
+ aIn1, aIn2, aIn3, aIn4, aIn5);
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationRunnable5::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5);
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationRunnable5(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3,
+ Arg4, Arg5))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn4, mArg4);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn5, mArg5);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5);
+ Tin1 mArg1;
+ Tin2 mArg2;
+ Tin3 mArg3;
+ Tin4 mArg4;
+ Tin5 mArg5;
+};
+
//
// Socket Interface
//
@@ -1985,6 +2732,233 @@ DispatchBluetoothResult(BluetoothResultHandler* aRes,
return rv;
}
+// Notification handling
+//
+
+BluetoothNotificationHandler::~BluetoothNotificationHandler()
+{ }
+
+static BluetoothNotificationHandler* sNotificationHandler;
+
+struct BluetoothCallback
+{
+ class NotificationHandlerWrapper
+ {
+ public:
+ typedef BluetoothNotificationHandler ObjectType;
+
+ static ObjectType* GetInstance()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ return sNotificationHandler;
+ }
+ };
+
+ // Notifications
+
+ typedef BluetoothNotificationRunnable1
+ AdapterStateChangedNotification;
+
+ typedef BluetoothNotificationRunnable3,
+ BluetoothStatus, int,
+ const BluetoothProperty*>
+ AdapterPropertiesNotification;
+
+ typedef BluetoothNotificationRunnable4,
+ BluetoothStatus, const nsAString&,
+ int, const BluetoothProperty*>
+ RemoteDevicePropertiesNotification;
+
+ typedef BluetoothNotificationRunnable2,
+ int, const BluetoothProperty*>
+ DeviceFoundNotification;
+
+ typedef BluetoothNotificationRunnable1
+ DiscoveryStateChangedNotification;
+
+ typedef BluetoothNotificationRunnable3
+ PinRequestNotification;
+
+ typedef BluetoothNotificationRunnable5
+ SspRequestNotification;
+
+ typedef BluetoothNotificationRunnable3
+ BondStateChangedNotification;
+
+ typedef BluetoothNotificationRunnable3
+ AclStateChangedNotification;
+
+ typedef BluetoothNotificationRunnable3,
+ uint8_t, uint16_t, const uint8_t*>
+ DutModeRecvNotification;
+
+ typedef BluetoothNotificationRunnable2
+ LeTestModeNotification;
+
+ // Bluedroid callbacks
+
+ static const bt_property_t*
+ AlignedProperties(bt_property_t* aProperties, size_t aNumProperties,
+ nsAutoArrayPtr& aPropertiesArray)
+ {
+ // See Bug 989976: consider aProperties address is not aligned. If
+ // it is aligned, we return the pointer directly; otherwise we make
+ // an aligned copy. The argument |aPropertiesArray| keeps track of
+ // the memory buffer.
+ if (!(reinterpret_cast(aProperties) % sizeof(void*))) {
+ return aProperties;
+ }
+
+ bt_property_t* properties = new bt_property_t[aNumProperties];
+ memcpy(properties, aProperties, aNumProperties * sizeof(*properties));
+ aPropertiesArray = properties;
+
+ return properties;
+ }
+
+ static void
+ AdapterStateChanged(bt_state_t aStatus)
+ {
+ AdapterStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::AdapterStateChangedNotification,
+ aStatus);
+ }
+
+ static void
+ AdapterProperties(bt_status_t aStatus, int aNumProperties,
+ bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ AdapterPropertiesNotification::Dispatch(
+ &BluetoothNotificationHandler::AdapterPropertiesNotification,
+ ConvertDefault(aStatus, STATUS_FAIL), aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ RemoteDeviceProperties(bt_status_t aStatus, bt_bdaddr_t* aBdAddress,
+ int aNumProperties, bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ RemoteDevicePropertiesNotification::Dispatch(
+ &BluetoothNotificationHandler::RemoteDevicePropertiesNotification,
+ ConvertDefault(aStatus, STATUS_FAIL), aBdAddress, aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ DeviceFound(int aNumProperties, bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ DeviceFoundNotification::Dispatch(
+ &BluetoothNotificationHandler::DeviceFoundNotification,
+ aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ DiscoveryStateChanged(bt_discovery_state_t aState)
+ {
+ DiscoveryStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::DiscoveryStateChangedNotification,
+ aState);
+ }
+
+ static void
+ PinRequest(bt_bdaddr_t* aRemoteBdAddress,
+ bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass)
+ {
+ PinRequestNotification::Dispatch(
+ &BluetoothNotificationHandler::PinRequestNotification,
+ aRemoteBdAddress, aRemoteBdName, aRemoteClass);
+ }
+
+ static void
+ SspRequest(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
+ uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant,
+ uint32_t aPasskey)
+ {
+ SspRequestNotification::Dispatch(
+ &BluetoothNotificationHandler::SspRequestNotification,
+ aRemoteBdAddress, aRemoteBdName, aRemoteClass,
+ aPairingVariant, aPasskey);
+ }
+
+ static void
+ BondStateChanged(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
+ bt_bond_state_t aState)
+ {
+ BondStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::BondStateChangedNotification,
+ aStatus, aRemoteBdAddress, aState);
+ }
+
+ static void
+ AclStateChanged(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
+ bt_acl_state_t aState)
+ {
+ AclStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::AclStateChangedNotification,
+ aStatus, aRemoteBdAddress, aState);
+ }
+
+ static void
+ ThreadEvt(bt_cb_thread_evt evt)
+ {
+ // This callback maintains internal state and is not exported.
+ }
+
+ static void
+ DutModeRecv(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen)
+ {
+ DutModeRecvNotification::Dispatch(
+ &BluetoothNotificationHandler::DutModeRecvNotification,
+ aOpcode, ConvertArray(aBuf, aLen), aLen);
+ }
+
+ static void
+ LeTestMode(bt_status_t aStatus, uint16_t aNumPackets)
+ {
+ LeTestModeNotification::Dispatch(
+ &BluetoothNotificationHandler::LeTestModeNotification,
+ aStatus, aNumPackets);
+ }
+};
+
+// Interface
+//
+
/* returns the container structure of a variable; _t is the container's
* type, _v the name of the variable, and _m is _v's field within _t
*/
@@ -2057,10 +3031,28 @@ BluetoothInterface::~BluetoothInterface()
{ }
void
-BluetoothInterface::Init(bt_callbacks_t* aCallbacks,
+BluetoothInterface::Init(BluetoothNotificationHandler* aNotificationHandler,
BluetoothResultHandler* aRes)
{
- int status = mInterface->init(aCallbacks);
+ static bt_callbacks_t sBluetoothCallbacks = {
+ sizeof(sBluetoothCallbacks),
+ .adapter_state_changed_cb = BluetoothCallback::AdapterStateChanged,
+ .adapter_properties_cb = BluetoothCallback::AdapterProperties,
+ .remote_device_properties_cb = BluetoothCallback::RemoteDeviceProperties,
+ .device_found_cb = BluetoothCallback::DeviceFound,
+ .discovery_state_changed_cb= BluetoothCallback::DiscoveryStateChanged,
+ .pin_request_cb = BluetoothCallback::PinRequest,
+ .ssp_request_cb = BluetoothCallback::SspRequest,
+ .bond_state_changed_cb = BluetoothCallback::BondStateChanged,
+ .acl_state_changed_cb = BluetoothCallback::AclStateChanged,
+ .thread_evt_cb = BluetoothCallback::ThreadEvt,
+ .dut_mode_recv_cb = BluetoothCallback::DutModeRecv,
+ .le_test_mode_cb = BluetoothCallback::LeTestMode
+ };
+
+ sNotificationHandler = aNotificationHandler;
+
+ int status = mInterface->init(&sBluetoothCallbacks);
if (aRes) {
DispatchBluetoothResult(aRes, &BluetoothResultHandler::Init,
@@ -2077,6 +3069,8 @@ BluetoothInterface::Cleanup(BluetoothResultHandler* aRes)
DispatchBluetoothResult(aRes, &BluetoothResultHandler::Cleanup,
STATUS_SUCCESS);
}
+
+ sNotificationHandler = nullptr;
}
void
diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.h b/dom/bluetooth/bluedroid/BluetoothInterface.h
index 3720e33e73e6..dc2a272fe8b7 100644
--- a/dom/bluetooth/bluedroid/BluetoothInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.h
@@ -326,6 +326,50 @@ private:
// Bluetooth Core Interface
//
+class BluetoothNotificationHandler
+{
+public:
+ virtual ~BluetoothNotificationHandler();
+
+ virtual void AdapterStateChangedNotification(bool aState) { }
+ virtual void AdapterPropertiesNotification(
+ BluetoothStatus aStatus, int aNumProperties,
+ const BluetoothProperty* aProperties) { }
+
+ virtual void RemoteDevicePropertiesNotification(
+ BluetoothStatus aStatus, const nsAString& aBdAddr,
+ int aNumProperties, const BluetoothProperty* aProperties) { }
+
+ virtual void DeviceFoundNotification(
+ int aNumProperties, const BluetoothProperty* aProperties) { }
+
+ virtual void DiscoveryStateChangedNotification(bool aState) { }
+
+ virtual void PinRequestNotification(const nsAString& aRemoteBdAddr,
+ const nsAString& aBdName, uint32_t aCod) { }
+ virtual void SspRequestNotification(const nsAString& aRemoteBdAddr,
+ const nsAString& aBdName,
+ uint32_t aCod,
+ const nsAString& aPairingVariant,
+ uint32_t aPassKey) { }
+
+ virtual void BondStateChangedNotification(BluetoothStatus aStatus,
+ const nsAString& aRemoteBdAddr,
+ BluetoothBondState aState) { }
+ virtual void AclStateChangedNotification(BluetoothStatus aStatus,
+ const nsAString& aRemoteBdAddr,
+ bool aState) { }
+
+ virtual void DutModeRecvNotification(uint16_t aOpcode,
+ const uint8_t* aBuf, uint8_t aLen) { }
+ virtual void LeTestModeNotification(BluetoothStatus aStatus,
+ uint16_t aNumPackets) { }
+
+protected:
+ BluetoothNotificationHandler()
+ { }
+};
+
class BluetoothResultHandler
{
public:
@@ -375,7 +419,8 @@ class BluetoothInterface
public:
static BluetoothInterface* GetInstance();
- void Init(bt_callbacks_t* aCallbacks, BluetoothResultHandler* aRes);
+ void Init(BluetoothNotificationHandler* aNotificationHandler,
+ BluetoothResultHandler* aRes);
void Cleanup(BluetoothResultHandler* aRes);
void Enable(BluetoothResultHandler* aRes);
diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
index 758ad680b82e..296d6486f7fb 100644
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -21,7 +21,6 @@
#include "BluetoothA2dpManager.h"
#include "BluetoothHfpManager.h"
#include "BluetoothOppManager.h"
-#include "BluetoothInterface.h"
#include "BluetoothProfileController.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothUtils.h"
@@ -41,7 +40,6 @@
} \
} while(0)
-#define MAX_UUID_SIZE 16
// Audio: Major service class = 0x100 (Bit 21 is set)
#define SET_AUDIO_BIT(cod) (cod |= 0x200000)
// Rendering: Major service class = 0x20 (Bit 18 is set)
@@ -51,12 +49,9 @@ using namespace mozilla;
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
-// TODO: Non thread-safe static variables
static nsString sAdapterBdAddress;
static nsString sAdapterBdName;
static InfallibleTArray sAdapterBondedAddressArray;
-
-// Static variables below should only be used on *main thread*
static BluetoothInterface* sBtInterface;
static nsTArray > sControllerArray;
static InfallibleTArray sRemoteDevicesPack;
@@ -65,41 +60,12 @@ static nsTArray > sSetPropertyRunnableArray;
static nsTArray > sGetDeviceRunnableArray;
static nsTArray > sBondingRunnableArray;
static nsTArray > sUnbondingRunnableArray;
-
-// Static variables below should only be used on *callback thread*
-
-
-// Atomic static variables
-static Atomic sAdapterDiscoverable(false);
-static Atomic sAdapterDiscoverableTimeout(0);
+static bool sAdapterDiscoverable(false);
+static uint32_t sAdapterDiscoverableTimeout(0);
/**
* Classes only used in this file
*/
-class DistributeBluetoothSignalTask MOZ_FINAL : public nsRunnable
-{
-public:
- DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
- mSignal(aSignal)
- {
- }
-
- NS_IMETHOD
- Run()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- BluetoothService* bs = BluetoothService::Get();
- NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
-
- bs->DistributeSignal(mSignal);
-
- return NS_OK;
- }
-
-private:
- BluetoothSignal mSignal;
-};
class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable
{
@@ -327,509 +293,6 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
return playStatus;
}
-/**
- * Bluedroid HAL callback functions
- *
- * Several callbacks are dispatched to main thread to avoid racing issues.
- */
-static void
-AdapterStateChangeCallback(bt_state_t aStatus)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- BT_LOGR("BT_STATE: %d", aStatus);
-
- bool isBtEnabled = (aStatus == BT_STATE_ON);
-
- if (!isBtEnabled &&
- NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
- BT_WARNING("Failed to dispatch to main thread!");
- return;
- }
-
- nsRefPtr runnable =
- new BluetoothService::ToggleBtAck(isBtEnabled);
- if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
- BT_WARNING("Failed to dispatch to main thread!");
- return;
- }
-
- if (isBtEnabled &&
- NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
- BT_WARNING("Failed to dispatch to main thread!");
- return;
- }
-}
-
-class AdapterPropertiesCallbackTask MOZ_FINAL : public nsRunnable
-{
-public:
- NS_IMETHOD
- Run()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!sSetPropertyRunnableArray.IsEmpty()) {
- DispatchBluetoothReply(sSetPropertyRunnableArray[0],
- BluetoothValue(true), EmptyString());
- sSetPropertyRunnableArray.RemoveElementAt(0);
- }
-
- return NS_OK;
- }
-};
-
-/**
- * AdapterPropertiesCallback will be called after enable() but before
- * AdapterStateChangeCallback is called. At that moment, both
- * BluetoothManager/BluetoothAdapter does not register observer yet.
- */
-static void
-AdapterPropertiesCallback(bt_status_t aStatus, int aNumProperties,
- bt_property_t *aProperties)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- BluetoothValue propertyValue;
- InfallibleTArray props;
-
- for (int i = 0; i < aNumProperties; i++) {
- bt_property_t p;
- // See Bug 989976, consider aProperties address is not aligned
- memcpy(&p, &aProperties[i], sizeof(p));
-
- if (p.type == BT_PROPERTY_BDADDR) {
- BdAddressTypeToString((bt_bdaddr_t*)p.val, sAdapterBdAddress);
- propertyValue = sAdapterBdAddress;
- BT_APPEND_NAMED_VALUE(props, "Address", propertyValue);
- } else if (p.type == BT_PROPERTY_BDNAME) {
- // Construct nsCString here because Bd name returned from bluedroid
- // is missing a null terminated character after SetProperty.
- propertyValue = sAdapterBdName = NS_ConvertUTF8toUTF16(
- nsCString((char*)p.val, p.len));
- BT_APPEND_NAMED_VALUE(props, "Name", propertyValue);
- } else if (p.type == BT_PROPERTY_ADAPTER_SCAN_MODE) {
- bt_scan_mode_t newMode = *(bt_scan_mode_t*)p.val;
-
- if (newMode == BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- propertyValue = sAdapterDiscoverable = true;
- } else {
- propertyValue = sAdapterDiscoverable = false;
- }
-
- BT_APPEND_NAMED_VALUE(props, "Discoverable", propertyValue);
- } else if (p.type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) {
- propertyValue = sAdapterDiscoverableTimeout = *(uint32_t*)p.val;
- BT_APPEND_NAMED_VALUE(props, "DiscoverableTimeout", propertyValue);
- } else if (p.type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
- // We have to cache addresses of bonded devices. Unlike BlueZ,
- // bluedroid would not send an another BT_PROPERTY_ADAPTER_BONDED_DEVICES
- // event after bond completed
- bt_bdaddr_t* deviceBdAddressTypes = (bt_bdaddr_t*)p.val;
- int numOfAddresses = p.len / BLUETOOTH_ADDRESS_BYTES;
- BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d", numOfAddresses);
-
- // Whenever reloading paired devices, force refresh
- sAdapterBondedAddressArray.Clear();
-
- for (int index = 0; index < numOfAddresses; index++) {
- nsAutoString deviceBdAddress;
- BdAddressTypeToString(deviceBdAddressTypes + index, deviceBdAddress);
- sAdapterBondedAddressArray.AppendElement(deviceBdAddress);
- }
-
- propertyValue = sAdapterBondedAddressArray;
- BT_APPEND_NAMED_VALUE(props, "Devices", propertyValue);
- } else if (p.type == BT_PROPERTY_UUIDS) {
- //FIXME: This will be implemented in the later patchset
- continue;
- } else {
- BT_LOGD("Unhandled adapter property type: %d", p.type);
- continue;
- }
- }
-
- NS_ENSURE_TRUE_VOID(props.Length() > 0);
-
- BluetoothValue value(props);
- BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
- NS_LITERAL_STRING(KEY_ADAPTER), value);
- nsRefPtr
- t = new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- }
-
- // Redirect to main thread to avoid racing problem
- NS_DispatchToMainThread(new AdapterPropertiesCallbackTask());
-}
-
-class RemoteDevicePropertiesCallbackTask : public nsRunnable
-{
- const InfallibleTArray mProps;
- nsString mRemoteDeviceBdAddress;
-public:
- RemoteDevicePropertiesCallbackTask(
- const InfallibleTArray& aProps,
- const nsAString& aRemoteDeviceBdAddress)
- : mProps(aProps)
- , mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
- { }
-
- NS_IMETHOD
- Run()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (sRequestedDeviceCountArray.IsEmpty()) {
- // This is possible because the callback would be called after turning
- // Bluetooth on.
- return NS_OK;
- }
-
- // Update to registered BluetoothDevice objects
- BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
- mRemoteDeviceBdAddress, mProps);
- nsRefPtr
- t = new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- return NS_OK;
- }
-
- // Use address as the index
- sRemoteDevicesPack.AppendElement(
- BluetoothNamedValue(mRemoteDeviceBdAddress, mProps));
-
- if (--sRequestedDeviceCountArray[0] == 0) {
- if (!sGetDeviceRunnableArray.IsEmpty()) {
- DispatchBluetoothReply(sGetDeviceRunnableArray[0],
- sRemoteDevicesPack, EmptyString());
- sGetDeviceRunnableArray.RemoveElementAt(0);
- }
-
- sRequestedDeviceCountArray.RemoveElementAt(0);
- sRemoteDevicesPack.Clear();
- }
-
- return NS_OK;
- }
-};
-
-/**
- * RemoteDevicePropertiesCallback will be called, as the following conditions:
- * 1. When BT is turning on, bluedroid automatically execute this callback
- * 2. When get_remote_device_properties()
- */
-static void
-RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
- int aNumProperties, bt_property_t *aProperties)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- InfallibleTArray props;
-
- nsString remoteDeviceBdAddress;
- BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress);
- BT_APPEND_NAMED_VALUE(props, "Address", remoteDeviceBdAddress);
-
- bool isCodInvalid = false;
- for (int i = 0; i < aNumProperties; ++i) {
- bt_property_t p = aProperties[i];
-
- if (p.type == BT_PROPERTY_BDNAME) {
- BluetoothValue propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
- BT_APPEND_NAMED_VALUE(props, "Name", propertyValue);
- } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
- uint32_t cod = *(uint32_t*)p.val;
- nsString icon;
- ClassToIcon(cod, icon);
- if (!icon.IsEmpty()) {
- // Valid CoD
- BT_APPEND_NAMED_VALUE(props, "Class", cod);
- BT_APPEND_NAMED_VALUE(props, "Icon", icon);
- } else {
- // If Cod is invalid, fallback to check UUIDs. It usually happens due to
- // NFC directly trigger pairing. bluedroid sends wrong CoD due to missing
- // EIR query records.
- isCodInvalid = true;
- }
- } else if (p.type == BT_PROPERTY_UUIDS) {
- InfallibleTArray uuidsArray;
- int uuidListLength = p.len / MAX_UUID_SIZE;
- uint32_t cod = 0;
-
- for (int i = 0; i < uuidListLength; i++) {
- uint16_t uuidServiceClass = UuidToServiceClassInt((bt_uuid_t*)(p.val +
- (i * MAX_UUID_SIZE)));
- BluetoothServiceClass serviceClass = BluetoothUuidHelper::
- GetBluetoothServiceClass(uuidServiceClass);
-
- // Get Uuid string from BluetoothServiceClass
- nsString uuid;
- BluetoothUuidHelper::GetString(serviceClass, uuid);
- uuidsArray.AppendElement(uuid);
-
- // Restore CoD value
- if (isCodInvalid) {
- if (serviceClass == BluetoothServiceClass::HANDSFREE ||
- serviceClass == BluetoothServiceClass::HEADSET) {
- BT_LOGD("Restore Class Of Device to Audio bit");
- SET_AUDIO_BIT(cod);
- } else if (serviceClass == BluetoothServiceClass::A2DP_SINK) {
- BT_LOGD("Restore Class of Device to Rendering bit");
- SET_RENDERING_BIT(cod);
- }
- }
- }
-
- if (isCodInvalid) {
- BT_APPEND_NAMED_VALUE(props, "Class", cod);
- // 'audio-card' refers to 'Audio' device
- BT_APPEND_NAMED_VALUE(props, "Icon", NS_LITERAL_STRING("audio-card"));
- }
- BT_APPEND_NAMED_VALUE(props, "UUIDS", uuidsArray);
- } else {
- BT_LOGD("Other non-handled device properties. Type: %d", p.type);
- }
- }
-
- // Redirect to main thread to avoid racing problem
- NS_DispatchToMainThread(
- new RemoteDevicePropertiesCallbackTask(props, remoteDeviceBdAddress));
-}
-
-static void
-DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- BluetoothValue propertyValue;
- InfallibleTArray propertiesArray;
-
- for (int i = 0; i < aNumProperties; i++) {
- bt_property_t p = aProperties[i];
-
- if (p.type == BT_PROPERTY_BDADDR) {
- nsString remoteDeviceBdAddress;
- BdAddressTypeToString((bt_bdaddr_t*)p.val, remoteDeviceBdAddress);
- propertyValue = remoteDeviceBdAddress;
-
- BT_APPEND_NAMED_VALUE(propertiesArray, "Address", propertyValue);
- } else if (p.type == BT_PROPERTY_BDNAME) {
- propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
- BT_APPEND_NAMED_VALUE(propertiesArray, "Name", propertyValue);
- } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
- uint32_t cod = *(uint32_t*)p.val;
- propertyValue = cod;
- BT_APPEND_NAMED_VALUE(propertiesArray, "Class", propertyValue);
-
- nsString icon;
- ClassToIcon(cod, icon);
- propertyValue = icon;
- BT_APPEND_NAMED_VALUE(propertiesArray, "Icon", propertyValue);
- } else {
- BT_LOGD("Not handled remote device property: %d", p.type);
- }
- }
-
- BluetoothValue value = propertiesArray;
- BluetoothSignal signal(NS_LITERAL_STRING("DeviceFound"),
- NS_LITERAL_STRING(KEY_ADAPTER), value);
- nsRefPtr
- t = new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- }
-}
-
-static void
-DiscoveryStateChangedCallback(bt_discovery_state_t aState)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- bool isDiscovering = (aState == BT_DISCOVERY_STARTED);
- BluetoothSignal signal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID),
- NS_LITERAL_STRING(KEY_ADAPTER), isDiscovering);
-
- nsRefPtr t =
- new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- }
-}
-
-static void
-PinRequestCallback(bt_bdaddr_t* aRemoteBdAddress,
- bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- InfallibleTArray propertiesArray;
- nsAutoString remoteAddress;
- BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
-
- BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
- BT_APPEND_NAMED_VALUE(propertiesArray, "method",
- NS_LITERAL_STRING("pincode"));
- BT_APPEND_NAMED_VALUE(propertiesArray, "name",
- NS_ConvertUTF8toUTF16(
- (const char*)aRemoteBdName->name));
-
- BluetoothValue value = propertiesArray;
- BluetoothSignal signal(NS_LITERAL_STRING("RequestPinCode"),
- NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
- nsRefPtr
- t = new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- }
-}
-
-static void
-SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
- uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant,
- uint32_t aPasskey)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- InfallibleTArray propertiesArray;
- nsAutoString remoteAddress;
- BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
-
- BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
- BT_APPEND_NAMED_VALUE(propertiesArray, "method",
- NS_LITERAL_STRING("confirmation"));
- BT_APPEND_NAMED_VALUE(propertiesArray, "name",
- NS_ConvertUTF8toUTF16(
- (const char*)aRemoteBdName->name));
- BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", aPasskey);
-
- BluetoothValue value = propertiesArray;
- BluetoothSignal signal(NS_LITERAL_STRING("RequestConfirmation"),
- NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
- nsRefPtr
- t = new DistributeBluetoothSignalTask(signal);
- if (NS_FAILED(NS_DispatchToMainThread(t))) {
- BT_WARNING("Failed to dispatch to main thread!");
- }
-}
-
-class BondStateChangedCallbackTask : public nsRunnable
-{
- nsString mRemoteDeviceBdAddress;
- bool mBonded;
-public:
- BondStateChangedCallbackTask(const nsAString& aRemoteDeviceBdAddress,
- bool aBonded)
- : mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
- , mBonded(aBonded)
- { }
-
- NS_IMETHOD
- Run()
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- if (mBonded && !sBondingRunnableArray.IsEmpty()) {
- DispatchBluetoothReply(sBondingRunnableArray[0],
- BluetoothValue(true), EmptyString());
-
- sBondingRunnableArray.RemoveElementAt(0);
- } else if (!mBonded && !sUnbondingRunnableArray.IsEmpty()) {
- DispatchBluetoothReply(sUnbondingRunnableArray[0],
- BluetoothValue(true), EmptyString());
-
- sUnbondingRunnableArray.RemoveElementAt(0);
- }
-
- // Update bonding status to gaia
- InfallibleTArray propertiesArray;
- BT_APPEND_NAMED_VALUE(propertiesArray, "address", mRemoteDeviceBdAddress);
- BT_APPEND_NAMED_VALUE(propertiesArray, "status", mBonded);
-
- BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
- NS_LITERAL_STRING(KEY_ADAPTER),
- BluetoothValue(propertiesArray));
- NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
-
- return NS_OK;
- }
-};
-
-static void
-BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
- bt_bond_state_t aState)
-{
- MOZ_ASSERT(!NS_IsMainThread());
-
- if (aState == BT_BOND_STATE_BONDING) {
- // No need to handle bonding state
- return;
- }
-
- nsAutoString remoteBdAddress;
- BdAddressTypeToString(aRemoteBdAddress, remoteBdAddress);
-
- if (aState == BT_BOND_STATE_BONDED &&
- sAdapterBondedAddressArray.Contains(remoteBdAddress)) {
- // See bug 940271 for more details about this case.
- return;
- }
-
- bool bonded;
- if (aState == BT_BOND_STATE_NONE) {
- bonded = false;
- sAdapterBondedAddressArray.RemoveElement(remoteBdAddress);
- } else if (aState == BT_BOND_STATE_BONDED) {
- bonded = true;
- sAdapterBondedAddressArray.AppendElement(remoteBdAddress);
- }
-
- // Update bonded address list to BluetoothAdapter
- InfallibleTArray propertiesChangeArray;
- BT_APPEND_NAMED_VALUE(propertiesChangeArray, "Devices",
- sAdapterBondedAddressArray);
-
- BluetoothValue value(propertiesChangeArray);
- BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
- NS_LITERAL_STRING(KEY_ADAPTER),
- BluetoothValue(propertiesChangeArray));
- NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
-
- // Redirect to main thread to avoid racing problem
- NS_DispatchToMainThread(
- new BondStateChangedCallbackTask(remoteBdAddress, bonded));
-}
-
-static void
-AclStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
- bt_acl_state_t aState)
-{
- //FIXME: This will be implemented in the later patchset
-}
-
-static void
-CallbackThreadEvent(bt_cb_thread_evt evt)
-{
- //FIXME: This will be implemented in the later patchset
-}
-
-bt_callbacks_t sBluetoothCallbacks =
-{
- sizeof(sBluetoothCallbacks),
- AdapterStateChangeCallback,
- AdapterPropertiesCallback,
- RemoteDevicePropertiesCallback,
- DeviceFoundCallback,
- DiscoveryStateChangedCallback,
- PinRequestCallback,
- SspRequestCallback,
- BondStateChangedCallback,
- AclStateChangedCallback,
- CallbackThreadEvent
-};
-
/**
* Static functions
*/
@@ -952,7 +415,8 @@ StartGonkBluetooth()
return NS_OK;
}
- sBtInterface->Init(&sBluetoothCallbacks, new InitResultHandler());
+ sBtInterface->Init(reinterpret_cast(bs),
+ new InitResultHandler());
return NS_OK;
}
@@ -1750,3 +1214,402 @@ BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)
{
}
+//
+// Bluetooth notifications
+//
+
+void
+BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ BT_LOGR("BT_STATE: %d", aState);
+
+ bool isBtEnabled = (aState == true);
+
+ if (!isBtEnabled &&
+ NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
+ BT_WARNING("Failed to dispatch to main thread!");
+ return;
+ }
+
+ nsRefPtr runnable =
+ new BluetoothService::ToggleBtAck(isBtEnabled);
+ if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
+ BT_WARNING("Failed to dispatch to main thread!");
+ return;
+ }
+
+ if (isBtEnabled &&
+ NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
+ BT_WARNING("Failed to dispatch to main thread!");
+ return;
+ }
+}
+
+/**
+ * AdapterPropertiesNotification will be called after enable() but
+ * before AdapterStateChangeCallback is called. At that moment, both
+ * BluetoothManager and BluetoothAdapter, do not register observer
+ * yet.
+ */
+void
+BluetoothServiceBluedroid::AdapterPropertiesNotification(
+ BluetoothStatus aStatus, int aNumProperties,
+ const BluetoothProperty* aProperties)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ BluetoothValue propertyValue;
+ InfallibleTArray props;
+
+ for (int i = 0; i < aNumProperties; i++) {
+
+ const BluetoothProperty& p = aProperties[i];
+
+ if (p.mType == PROPERTY_BDADDR) {
+ sAdapterBdAddress = p.mString;
+ propertyValue = sAdapterBdAddress;
+ BT_APPEND_NAMED_VALUE(props, "Address", propertyValue);
+
+ } else if (p.mType == PROPERTY_BDNAME) {
+ sAdapterBdName = p.mString;
+ propertyValue = sAdapterBdName;
+ BT_APPEND_NAMED_VALUE(props, "Name", propertyValue);
+
+ } else if (p.mType == PROPERTY_ADAPTER_SCAN_MODE) {
+ BluetoothScanMode newMode = p.mScanMode;
+
+ if (newMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+ propertyValue = sAdapterDiscoverable = true;
+ } else {
+ propertyValue = sAdapterDiscoverable = false;
+ }
+
+ BT_APPEND_NAMED_VALUE(props, "Discoverable", propertyValue);
+
+ } else if (p.mType == PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) {
+ propertyValue = sAdapterDiscoverableTimeout = p.mUint32;
+ BT_APPEND_NAMED_VALUE(props, "DiscoverableTimeout", propertyValue);
+
+ } else if (p.mType == PROPERTY_ADAPTER_BONDED_DEVICES) {
+ // We have to cache addresses of bonded devices. Unlike BlueZ,
+ // Bluedroid would not send another PROPERTY_ADAPTER_BONDED_DEVICES
+ // event after bond completed.
+ BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d",
+ p.mStringArray.Length());
+
+ // Whenever reloading paired devices, force refresh
+ sAdapterBondedAddressArray.Clear();
+
+ for (size_t index = 0; index < p.mStringArray.Length(); index++) {
+ sAdapterBondedAddressArray.AppendElement(p.mStringArray[index]);
+ }
+
+ propertyValue = sAdapterBondedAddressArray;
+ BT_APPEND_NAMED_VALUE(props, "Devices", propertyValue);
+
+ } else if (p.mType == PROPERTY_UUIDS) {
+ //FIXME: This will be implemented in the later patchset
+ continue;
+ } else {
+ BT_LOGD("Unhandled adapter property type: %d", p.mType);
+ continue;
+ }
+ }
+
+ NS_ENSURE_TRUE_VOID(props.Length() > 0);
+
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PropertyChanged"),
+ NS_LITERAL_STRING(KEY_ADAPTER),
+ BluetoothValue(props)));
+
+ // Send reply for SetProperty
+
+ if (!sSetPropertyRunnableArray.IsEmpty()) {
+ DispatchBluetoothReply(sSetPropertyRunnableArray[0],
+ BluetoothValue(true), EmptyString());
+ sSetPropertyRunnableArray.RemoveElementAt(0);
+ }
+}
+
+/**
+ * RemoteDevicePropertiesNotification will be called
+ *
+ * (1) automatically by Bluedroid when BT is turning on, or
+ * (2) as result of GetRemoteDeviceProperties.
+ */
+void
+BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
+ BluetoothStatus aStatus, const nsAString& aBdAddr,
+ int aNumProperties, const BluetoothProperty* aProperties)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ InfallibleTArray props;
+
+ BT_APPEND_NAMED_VALUE(props, "Address", BluetoothValue(nsString(aBdAddr)));
+
+ bool isCodInvalid = false;
+ for (int i = 0; i < aNumProperties; ++i) {
+
+ const BluetoothProperty& p = aProperties[i];
+
+ if (p.mType == PROPERTY_BDNAME) {
+ BT_APPEND_NAMED_VALUE(props, "Name", p.mString);
+ } else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
+ uint32_t cod = p.mUint32;
+ nsString icon;
+ ClassToIcon(cod, icon);
+ if (!icon.IsEmpty()) {
+ // Valid CoD
+ BT_APPEND_NAMED_VALUE(props, "Class", cod);
+ BT_APPEND_NAMED_VALUE(props, "Icon", icon);
+ } else {
+ // If Cod is invalid, fallback to check UUIDs. It usually happens due to
+ // NFC directly trigger pairing. bluedroid sends wrong CoD due to missing
+ // EIR query records.
+ isCodInvalid = true;
+ }
+ } else if (p.mType == PROPERTY_UUIDS) {
+ InfallibleTArray uuidsArray;
+ uint32_t cod = 0;
+
+ for (size_t i = 0; i < p.mUuidArray.Length(); i++) {
+ uint16_t uuidServiceClass = UuidToServiceClassInt(p.mUuidArray[i]);
+ BluetoothServiceClass serviceClass =
+ BluetoothUuidHelper::GetBluetoothServiceClass(uuidServiceClass);
+
+ // Get Uuid string from BluetoothServiceClass
+ nsString uuid;
+ BluetoothUuidHelper::GetString(serviceClass, uuid);
+ uuidsArray.AppendElement(uuid);
+
+ // Restore CoD value
+ if (isCodInvalid) {
+ if (serviceClass == BluetoothServiceClass::HANDSFREE ||
+ serviceClass == BluetoothServiceClass::HEADSET) {
+ BT_LOGD("Restore Class Of Device to Audio bit");
+ SET_AUDIO_BIT(cod);
+ } else if (serviceClass == BluetoothServiceClass::A2DP_SINK) {
+ BT_LOGD("Restore Class of Device to Rendering bit");
+ SET_RENDERING_BIT(cod);
+ }
+ }
+ }
+
+ if (isCodInvalid) {
+ BT_APPEND_NAMED_VALUE(props, "Class", cod);
+ // 'audio-card' refers to 'Audio' device
+ BT_APPEND_NAMED_VALUE(props, "Icon", NS_LITERAL_STRING("audio-card"));
+ }
+ BT_APPEND_NAMED_VALUE(props, "UUIDS", uuidsArray);
+ } else {
+ BT_LOGD("Other non-handled device properties. Type: %d", p.mType);
+ }
+ }
+
+ if (sRequestedDeviceCountArray.IsEmpty()) {
+ // This is possible because the callback would be called after turning
+ // Bluetooth on.
+ return;
+ }
+
+ // Use address as the index
+ sRemoteDevicesPack.AppendElement(
+ BluetoothNamedValue(nsString(aBdAddr), props));
+
+ if (--sRequestedDeviceCountArray[0] == 0) {
+ if (!sGetDeviceRunnableArray.IsEmpty()) {
+ DispatchBluetoothReply(sGetDeviceRunnableArray[0],
+ sRemoteDevicesPack, EmptyString());
+ sGetDeviceRunnableArray.RemoveElementAt(0);
+ }
+
+ sRequestedDeviceCountArray.RemoveElementAt(0);
+ sRemoteDevicesPack.Clear();
+ }
+
+ // Update to registered BluetoothDevice objects
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PropertyChanged"),
+ nsString(aBdAddr),
+ BluetoothValue(props)));
+}
+
+void
+BluetoothServiceBluedroid::DeviceFoundNotification(
+ int aNumProperties, const BluetoothProperty* aProperties)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ BluetoothValue propertyValue;
+ InfallibleTArray propertiesArray;
+
+ for (int i = 0; i < aNumProperties; i++) {
+
+ const BluetoothProperty& p = aProperties[i];
+
+ if (p.mType == PROPERTY_BDADDR) {
+ propertyValue = p.mString;
+
+ BT_APPEND_NAMED_VALUE(propertiesArray, "Address", propertyValue);
+ } else if (p.mType == PROPERTY_BDNAME) {
+ BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString);
+ } else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
+ uint32_t cod = p.mUint32;
+ propertyValue = cod;
+ BT_APPEND_NAMED_VALUE(propertiesArray, "Class", propertyValue);
+
+ nsString icon;
+ ClassToIcon(cod, icon);
+ propertyValue = icon;
+ BT_APPEND_NAMED_VALUE(propertiesArray, "Icon", propertyValue);
+ } else {
+ BT_LOGD("Not handled remote device property: %d", p.mType);
+ }
+ }
+
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("DeviceFound"),
+ NS_LITERAL_STRING(KEY_ADAPTER),
+ BluetoothValue(propertiesArray)));
+}
+
+void
+BluetoothServiceBluedroid::DiscoveryStateChangedNotification(bool aState)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ bool isDiscovering = (aState == true);
+
+ DistributeSignal(
+ BluetoothSignal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID),
+ NS_LITERAL_STRING(KEY_ADAPTER), isDiscovering));
+}
+
+void
+BluetoothServiceBluedroid::PinRequestNotification(const nsAString& aRemoteBdAddr,
+ const nsAString& aBdName,
+ uint32_t aCod)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ InfallibleTArray propertiesArray;
+
+ BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "method",
+ NS_LITERAL_STRING("pincode"));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "name", nsString(aBdName));
+
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("RequestPinCode"),
+ NS_LITERAL_STRING(KEY_LOCAL_AGENT),
+ BluetoothValue(propertiesArray)));
+}
+
+void
+BluetoothServiceBluedroid::SspRequestNotification(
+ const nsAString& aRemoteBdAddr, const nsAString& aBdName, uint32_t aCod,
+ const nsAString& aPairingaVariant, uint32_t aPassKey)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ InfallibleTArray propertiesArray;
+
+ BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "method",
+ NS_LITERAL_STRING("confirmation"));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "name", nsString(aBdName));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", aPassKey);
+
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("RequestConfirmation"),
+ NS_LITERAL_STRING(KEY_LOCAL_AGENT),
+ BluetoothValue(propertiesArray)));
+}
+
+void
+BluetoothServiceBluedroid::BondStateChangedNotification(
+ BluetoothStatus aStatus, const nsAString& aRemoteBdAddr,
+ BluetoothBondState aState)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (aState == BOND_STATE_BONDING) {
+ // No need to handle bonding state
+ return;
+ }
+
+ if (aState == BOND_STATE_BONDED &&
+ sAdapterBondedAddressArray.Contains(aRemoteBdAddr)) {
+ // See bug 940271 for more details about this case.
+ return;
+ }
+
+ bool bonded;
+ if (aState == BOND_STATE_NONE) {
+ bonded = false;
+ sAdapterBondedAddressArray.RemoveElement(aRemoteBdAddr);
+ } else if (aState == BOND_STATE_BONDED) {
+ bonded = true;
+ sAdapterBondedAddressArray.AppendElement(aRemoteBdAddr);
+ } else {
+ return;
+ }
+
+ // Update bonded address list to BluetoothAdapter
+ InfallibleTArray propertiesChangeArray;
+ BT_APPEND_NAMED_VALUE(propertiesChangeArray, "Devices",
+ sAdapterBondedAddressArray);
+
+ DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("PropertyChanged"),
+ NS_LITERAL_STRING(KEY_ADAPTER),
+ BluetoothValue(propertiesChangeArray)));
+
+ if (bonded && !sBondingRunnableArray.IsEmpty()) {
+ DispatchBluetoothReply(sBondingRunnableArray[0],
+ BluetoothValue(true), EmptyString());
+
+ sBondingRunnableArray.RemoveElementAt(0);
+ } else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
+ DispatchBluetoothReply(sUnbondingRunnableArray[0],
+ BluetoothValue(true), EmptyString());
+
+ sUnbondingRunnableArray.RemoveElementAt(0);
+ }
+
+ // Update bonding status to gaia
+ InfallibleTArray propertiesArray;
+ BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
+ BT_APPEND_NAMED_VALUE(propertiesArray, "status", bonded);
+
+ DistributeSignal(
+ BluetoothSignal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
+ NS_LITERAL_STRING(KEY_ADAPTER),
+ BluetoothValue(propertiesArray)));
+}
+
+void
+BluetoothServiceBluedroid::AclStateChangedNotification(
+ BluetoothStatus aStatus, const nsAString& aRemoteBdAddr, bool aState)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ // FIXME: This will be implemented in the later patchset
+}
+
+void
+BluetoothServiceBluedroid::DutModeRecvNotification(uint16_t aOpcode,
+ const uint8_t* aBuf,
+ uint8_t aLen)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ // FIXME: This will be implemented in the later patchset
+}
+
+void
+BluetoothServiceBluedroid::LeTestModeNotification(BluetoothStatus aStatus,
+ uint16_t aNumPackets)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ // FIXME: This will be implemented in the later patchset
+}
diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
index c77bb991f6ef..60d3651ad397 100644
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
@@ -8,11 +8,13 @@
#define mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
#include "BluetoothCommon.h"
+#include "BluetoothInterface.h"
#include "BluetoothService.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothServiceBluedroid : public BluetoothService
+ , public BluetoothNotificationHandler
{
public:
BluetoothServiceBluedroid();
@@ -153,6 +155,46 @@ public:
virtual nsresult
SendInputMessage(const nsAString& aDeviceAddresses,
const nsAString& aMessage) MOZ_OVERRIDE;
+
+ //
+ // Bluetooth notifications
+ //
+
+ virtual void AdapterStateChangedNotification(bool aState) MOZ_OVERRIDE;
+ virtual void AdapterPropertiesNotification(
+ BluetoothStatus aStatus, int aNumProperties,
+ const BluetoothProperty* aProperties) MOZ_OVERRIDE;
+
+ virtual void RemoteDevicePropertiesNotification(
+ BluetoothStatus aStatus, const nsAString& aBdAddr,
+ int aNumProperties, const BluetoothProperty* aProperties) MOZ_OVERRIDE;
+
+ virtual void DeviceFoundNotification(
+ int aNumProperties, const BluetoothProperty* aProperties) MOZ_OVERRIDE;
+
+ virtual void DiscoveryStateChangedNotification(bool aState) MOZ_OVERRIDE;
+
+ virtual void PinRequestNotification(const nsAString& aRemoteBdAddr,
+ const nsAString& aBdName,
+ uint32_t aCod) MOZ_OVERRIDE;
+ virtual void SspRequestNotification(const nsAString& aRemoteBdAddr,
+ const nsAString& aBdName,
+ uint32_t aCod,
+ const nsAString& aPairingaVariant,
+ uint32_t aPassKey) MOZ_OVERRIDE;
+
+ virtual void BondStateChangedNotification(
+ BluetoothStatus aStatus, const nsAString& aRemoteBdAddr,
+ BluetoothBondState aState) MOZ_OVERRIDE;
+ virtual void AclStateChangedNotification(BluetoothStatus aStatus,
+ const nsAString& aRemoteBdAddr,
+ bool aState) MOZ_OVERRIDE;
+
+ virtual void DutModeRecvNotification(uint16_t aOpcode,
+ const uint8_t* aBuf,
+ uint8_t aLen) MOZ_OVERRIDE;
+ virtual void LeTestModeNotification(BluetoothStatus aStatus,
+ uint16_t aNumPackets) MOZ_OVERRIDE;
};
END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.cpp b/dom/bluetooth/bluedroid/BluetoothUtils.cpp
index eb2b0e546e51..c89efef54f8a 100644
--- a/dom/bluetooth/bluedroid/BluetoothUtils.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothUtils.cpp
@@ -23,19 +23,6 @@
BEGIN_BLUETOOTH_NAMESPACE
-void
-StringToBdAddressType(const nsAString& aBdAddress,
- bt_bdaddr_t *aRetBdAddressType)
-{
- NS_ConvertUTF16toUTF8 bdAddressUTF8(aBdAddress);
- const char* str = bdAddressUTF8.get();
-
- for (int i = 0; i < 6; i++) {
- aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
- str++;
- }
-}
-
void
BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
{
@@ -50,11 +37,11 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
}
uint16_t
-UuidToServiceClassInt(bt_uuid_t* p_uuid)
+UuidToServiceClassInt(const BluetoothUuid& mUuid)
{
// extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb
uint16_t shortUuid;
- memcpy(&shortUuid, &(p_uuid->uu[2]), sizeof(uint16_t));
+ memcpy(&shortUuid, mUuid.mUuid + 2, sizeof(uint16_t));
return ntohs(shortUuid);
}
diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.h b/dom/bluetooth/bluedroid/BluetoothUtils.h
index 40bd2392bc14..4cf0c470cb19 100644
--- a/dom/bluetooth/bluedroid/BluetoothUtils.h
+++ b/dom/bluetooth/bluedroid/BluetoothUtils.h
@@ -18,16 +18,12 @@ class BluetoothNamedValue;
class BluetoothValue;
class BluetoothReplyRunnable;
-void
-StringToBdAddressType(const nsAString& aBdAddress,
- bt_bdaddr_t *aRetBdAddressType);
-
void
BdAddressTypeToString(bt_bdaddr_t* aBdAddressType,
nsAString& aRetBdAddress);
uint16_t
-UuidToServiceClassInt(bt_uuid_t* p_uuid);
+UuidToServiceClassInt(const BluetoothUuid& mUuid);
bool
SetJsObject(JSContext* aContext,
diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js
index abeda31582c6..887c55d41d6b 100644
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -644,15 +644,15 @@ BrowserElementChild.prototype = {
isCollapsed: (e.selectedText.length == 0),
};
- // Get correct geometry information if we have nested