mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to mozilla-inbound
This commit is contained in:
commit
59d863b149
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="20a1521efdac44c8219f00c2414de031891fb464"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
@ -132,7 +132,7 @@
|
||||
<!-- Flame specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="960533f716ce31dfad357e87fa2f1d9ee5e94674"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="52c909e821d107d414f851e267dedcd7aae2cebf"/>
|
||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="893238eb1215f8fd4f3747169170cc5e1cc33969"/>
|
||||
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
|
||||
<project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="30b96dfca99cb384bf520a16b81f3aba56f09907"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="20a1521efdac44c8219f00c2414de031891fb464"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "253fcdd727387f6ad023de9aed30a20e7b8bd72d",
|
||||
"revision": "95521d1e0cf64f0d95be0cf643931e20119a7387",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="20a1521efdac44c8219f00c2414de031891fb464"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a06714c555ca7068545f10b4437a16c14cd8e7f5"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e9aa22d15b77e5b3d7e763128ead2caffd3b801"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -159,7 +159,6 @@
|
||||
@BINPATH@/components/dom_system_gonk.xpt
|
||||
#endif
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
@BINPATH@/components/dom_icc.xpt
|
||||
@BINPATH@/components/dom_cellbroadcast.xpt
|
||||
@BINPATH@/components/dom_wappush.xpt
|
||||
@ -200,6 +199,7 @@
|
||||
@BINPATH@/components/dom_threads.xpt
|
||||
@BINPATH@/components/dom_traversal.xpt
|
||||
@BINPATH@/components/dom_views.xpt
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechrecognition.xpt
|
||||
#endif
|
||||
@ -448,6 +448,8 @@
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/TelephonyService.js
|
||||
@BINPATH@/components/TelephonyService.manifest
|
||||
@BINPATH@/components/VoicemailService.js
|
||||
@BINPATH@/components/VoicemailService.manifest
|
||||
#endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
|
@ -1605,7 +1605,7 @@ pref("loop.soft_start_hostname", "soft-start.loop.services.mozilla.com");
|
||||
|
||||
pref("loop.server", "https://loop.services.mozilla.com");
|
||||
pref("loop.seenToS", "unseen");
|
||||
pref("loop.legal.ToS_url", "https://accounts.firefox.com/legal/terms");
|
||||
pref("loop.legal.ToS_url", "https://call.mozilla.com/legal/terms/");
|
||||
pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/");
|
||||
pref("loop.do_not_disturb", false);
|
||||
pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
|
||||
@ -1613,6 +1613,7 @@ pref("loop.retry_delay.start", 60000);
|
||||
pref("loop.retry_delay.limit", 300000);
|
||||
pref("loop.feedback.baseUrl", "https://input.mozilla.org/api/v1/feedback");
|
||||
pref("loop.feedback.product", "Loop");
|
||||
pref("loop.debug.loglevel", "Error");
|
||||
pref("loop.debug.websocket", false);
|
||||
pref("loop.debug.sdk", false);
|
||||
|
||||
|
@ -11,7 +11,6 @@ let gCustomize = {
|
||||
"classic",
|
||||
"enhanced",
|
||||
"panel",
|
||||
"what",
|
||||
],
|
||||
|
||||
_nodes: {},
|
||||
@ -33,9 +32,6 @@ let gCustomize = {
|
||||
gAllPages.enabled = true;
|
||||
gAllPages.enhanced = true;
|
||||
});
|
||||
this._nodes.what.addEventListener("click", e => {
|
||||
gIntro.showPanel();
|
||||
});
|
||||
|
||||
this.updateSelected();
|
||||
},
|
||||
|
@ -11,6 +11,7 @@ let gIntro = {
|
||||
|
||||
_nodeIDSuffixes: [
|
||||
"panel",
|
||||
"what",
|
||||
],
|
||||
|
||||
_nodes: {},
|
||||
@ -21,6 +22,7 @@ let gIntro = {
|
||||
}
|
||||
|
||||
this._nodes.panel.addEventListener("popupshowing", e => this._setUpPanel());
|
||||
this._nodes.what.addEventListener("click", e => this.showPanel());
|
||||
},
|
||||
|
||||
showIfNecessary: function() {
|
||||
@ -31,11 +33,8 @@ let gIntro = {
|
||||
},
|
||||
|
||||
showPanel: function() {
|
||||
// Open the customize menu first
|
||||
gCustomize.showPanel().then(nodes => {
|
||||
// Point the panel at the 'what' menu item
|
||||
this._nodes.panel.openPopup(nodes.what);
|
||||
});
|
||||
// Point the panel at the 'what' link
|
||||
this._nodes.panel.openPopup(this._nodes.what);
|
||||
},
|
||||
|
||||
_setUpPanel: function() {
|
||||
|
@ -49,21 +49,41 @@ input[type=button] {
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-intro-what {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 55px;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
#newtab-intro-what:-moz-locale-dir(rtl) {
|
||||
left: 55px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-intro-panel {
|
||||
color: #737373;
|
||||
color: #6a7b86;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
margin-top: -32px;
|
||||
padding: 10px;
|
||||
width: 500px;
|
||||
line-height: 19px;
|
||||
width: 520px;
|
||||
}
|
||||
|
||||
#newtab-intro-panel h1 {
|
||||
color: #343f48;
|
||||
font-family: Open Sans, sans-serif;
|
||||
font-size: 30px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#newtab-intro-panel p {
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
#newtab-intro-panel p:last-child {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#newtab-intro-what:hover,
|
||||
#newtab-intro-panel a {
|
||||
color: #4a90e2;
|
||||
}
|
||||
@ -231,12 +251,12 @@ input[type=button] {
|
||||
|
||||
#newtab-intro-panel input,
|
||||
.sponsored-explain input {
|
||||
background-size: 20px;
|
||||
height: 20px;
|
||||
background-size: 18px;
|
||||
height: 18px;
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
position: static;
|
||||
width: 20px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
/* CONTROLS */
|
||||
|
@ -21,7 +21,7 @@
|
||||
title="&newtab.pageTitle;">
|
||||
|
||||
<xul:panel id="newtab-intro-panel" orient="vertical" type="arrow"
|
||||
noautohide="true" position="leftcenter topright">
|
||||
noautohide="true">
|
||||
<h1>&newtab.intro.header;</h1>
|
||||
</xul:panel>
|
||||
|
||||
@ -43,9 +43,6 @@
|
||||
<xul:hbox id="newtab-customize-blank" class="newtab-customize-panel-item">
|
||||
<xul:label>&newtab.customize.blank;</xul:label>
|
||||
</xul:hbox>
|
||||
<xul:hbox id="newtab-customize-what" class="newtab-customize-panel-item">
|
||||
<xul:label>&newtab.customize.what;</xul:label>
|
||||
</xul:hbox>
|
||||
</xul:panel>
|
||||
|
||||
<div id="newtab-scrollbox">
|
||||
@ -93,6 +90,8 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div id="newtab-intro-what">&newtab.customize.what;</div>
|
||||
|
||||
<input id="newtab-customize-button" type="button" title="&newtab.customize.title;"/>
|
||||
</div>
|
||||
|
||||
|
@ -102,6 +102,11 @@ skip-if = os == "linux" # Bug 924307
|
||||
skip-if = e10s # Bug ?????? - no about:home support yet
|
||||
[browser_aboutSyncProgress.js]
|
||||
[browser_action_keyword.js]
|
||||
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
|
||||
[browser_action_searchengine.js]
|
||||
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
|
||||
[browser_action_searchengine_alias.js]
|
||||
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
|
||||
[browser_addKeywordSearch.js]
|
||||
skip-if = e10s
|
||||
[browser_alltabslistener.js]
|
||||
@ -193,7 +198,6 @@ skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug555767.js]
|
||||
skip-if = e10s # Bug 916974 - Session history doesn't work in e10s
|
||||
[browser_bug556061.js]
|
||||
skip-if = e10s # Bug 932651 - getClipboardData in specialpowersAPI.js not e10s friendly
|
||||
[browser_bug559991.js]
|
||||
skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug561623.js]
|
||||
@ -440,7 +444,7 @@ skip-if = e10s
|
||||
[browser_urlbarAutoFillTrimURLs.js]
|
||||
skip-if = e10s
|
||||
[browser_urlbarCopying.js]
|
||||
skip-if = e10s # Bug 932651 - getClipboardData in specialpowersAPI.js not e10s friendly
|
||||
skip-if = e10s # Bug 1069757 - browser_urlbarCopying.js needs e10s love.
|
||||
[browser_urlbarEnter.js]
|
||||
skip-if = e10s # Bug ?????? - obscure non-windows child process crashes on try
|
||||
[browser_urlbarRevert.js]
|
||||
|
@ -8,9 +8,6 @@ function* promise_first_result(inputText) {
|
||||
gURLBar.value = inputText.slice(0, -1);
|
||||
EventUtils.synthesizeKey(inputText.slice(-1) , {});
|
||||
yield promiseSearchComplete();
|
||||
// On Linux, the popup may or may not be open at this stage. So we need
|
||||
// additional checks to ensure we wait long enough.
|
||||
yield promisePopupShown(gURLBar.popup);
|
||||
|
||||
let firstResult = gURLBar.popup.richlistbox.firstChild;
|
||||
return firstResult;
|
||||
|
@ -0,0 +1,51 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let gOriginalEngine;
|
||||
|
||||
function* promise_first_result(inputText) {
|
||||
gURLBar.focus();
|
||||
gURLBar.value = inputText.slice(0, -1);
|
||||
EventUtils.synthesizeKey(inputText.slice(-1) , {});
|
||||
yield promiseSearchComplete();
|
||||
// On Linux, the popup may or may not be open at this stage. So we need
|
||||
// additional checks to ensure we wait long enough.
|
||||
yield promisePopupShown(gURLBar.popup);
|
||||
|
||||
let firstResult = gURLBar.popup.richlistbox.firstChild;
|
||||
return firstResult;
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
// This test is only relevant if UnifiedComplete is enabled.
|
||||
if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
|
||||
return;
|
||||
|
||||
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
|
||||
"http://example.com/?q={searchTerms}");
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
gOriginalEngine = Services.search.currentEngine;
|
||||
Services.search.currentEngine = engine;
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.search.currentEngine = gOriginalEngine;
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
Services.search.removeEngine(engine);
|
||||
|
||||
try {
|
||||
gBrowser.removeTab(tab);
|
||||
} catch(ex) { /* tab may have already been closed in case of failure */ }
|
||||
|
||||
return promiseClearHistory();
|
||||
});
|
||||
|
||||
let result = yield promise_first_result("open a search");
|
||||
isnot(result, null, "Should have a result");
|
||||
let tabPromise = promiseTabLoaded(gBrowser.selectedTab);
|
||||
EventUtils.synthesizeMouseAtCenter(result, {});
|
||||
yield tabPromise;
|
||||
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
|
||||
});
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
**/
|
||||
|
||||
let gOriginalEngine;
|
||||
|
||||
add_task(function* () {
|
||||
// This test is only relevant if UnifiedComplete is enabled.
|
||||
if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
|
||||
return;
|
||||
|
||||
Services.search.addEngineWithDetails("MozSearch", "", "moz", "", "GET",
|
||||
"http://example.com/?q={searchTerms}");
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
gOriginalEngine = Services.search.currentEngine;
|
||||
Services.search.currentEngine = engine;
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.search.currentEngine = gOriginalEngine;
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
Services.search.removeEngine(engine);
|
||||
|
||||
try {
|
||||
gBrowser.removeTab(tab);
|
||||
} catch(ex) { /* tab may have already been closed in case of failure */ }
|
||||
|
||||
return promiseClearHistory();
|
||||
});
|
||||
|
||||
gURLBar.focus();
|
||||
gURLBar.value = "moz open a searc";
|
||||
EventUtils.synthesizeKey("h" , {});
|
||||
yield promiseSearchComplete();
|
||||
|
||||
EventUtils.synthesizeKey("VK_RETURN" , { });
|
||||
yield promiseTabLoaded(gBrowser.selectedTab);
|
||||
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
|
||||
});
|
@ -6,13 +6,11 @@ function* check_a11y_label(inputText, expectedLabel) {
|
||||
gURLBar.value = inputText.slice(0, -1);
|
||||
EventUtils.synthesizeKey(inputText.slice(-1) , {});
|
||||
yield promiseSearchComplete();
|
||||
// On Linux, the popup may or may not be open at this stage. So we need
|
||||
// additional checks to ensure we wait long enough.
|
||||
yield promisePopupShown(gURLBar.popup);
|
||||
|
||||
let firstResult = gURLBar.popup.richlistbox.firstChild;
|
||||
is(firstResult.getAttribute("type"), "action switchtab", "Expect right type attribute");
|
||||
is(firstResult.label, expectedLabel, "Result a11y label should be as expected");
|
||||
ok(gURLBar.popup.richlistbox.children.length > 1, "Should get at least 2 results");
|
||||
let result = gURLBar.popup.richlistbox.children[1];
|
||||
is(result.getAttribute("type"), "action switchtab", "Expect right type attribute");
|
||||
is(result.label, expectedLabel, "Result a11y label should be as expected");
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
|
@ -3,6 +3,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
add_task(function* test_switchtab_override() {
|
||||
// This test is only relevant if UnifiedComplete is enabled.
|
||||
if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
|
||||
return;
|
||||
|
||||
let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
|
||||
|
||||
info("Opening first tab");
|
||||
@ -37,7 +41,8 @@ add_task(function* test_switchtab_override() {
|
||||
EventUtils.synthesizeKey("e" , {});
|
||||
yield deferred.promise;
|
||||
|
||||
info("Select first autocomplete popup entry");
|
||||
info("Select second autocomplete popup entry");
|
||||
EventUtils.synthesizeKey("VK_DOWN" , {});
|
||||
EventUtils.synthesizeKey("VK_DOWN" , {});
|
||||
ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");
|
||||
|
||||
|
@ -38,7 +38,8 @@ add_task(function* test_switchtab_override_keynav() {
|
||||
EventUtils.synthesizeKey("e" , {});
|
||||
yield searchDeferred.promise;
|
||||
|
||||
info("Select first autocomplete popup entry");
|
||||
info("Select second autocomplete popup entry");
|
||||
EventUtils.synthesizeKey("VK_DOWN" , {});
|
||||
EventUtils.synthesizeKey("VK_DOWN" , {});
|
||||
ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");
|
||||
|
||||
|
@ -740,23 +740,28 @@ function promisePopupHidden(popup) {
|
||||
return promisePopupEvent(popup, "hidden");
|
||||
}
|
||||
|
||||
// NOTE: If you're using this, and attempting to interact with one of the
|
||||
// autocomplete results, your test is likely to be unreliable on Linux.
|
||||
// See bug 1073339.
|
||||
let gURLBarOnSearchComplete = null;
|
||||
function promiseSearchComplete() {
|
||||
info("Waiting for onSearchComplete");
|
||||
let deferred = Promise.defer();
|
||||
|
||||
if (!gURLBarOnSearchComplete) {
|
||||
gURLBarOnSearchComplete = gURLBar.onSearchComplete;
|
||||
registerCleanupFunction(() => {
|
||||
gURLBar.onSearchComplete = gURLBarOnSearchComplete;
|
||||
});
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
if (!gURLBarOnSearchComplete) {
|
||||
gURLBarOnSearchComplete = gURLBar.onSearchComplete;
|
||||
registerCleanupFunction(() => {
|
||||
gURLBar.onSearchComplete = gURLBarOnSearchComplete;
|
||||
});
|
||||
}
|
||||
|
||||
gURLBar.onSearchComplete = function () {
|
||||
ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
|
||||
gURLBarOnSearchComplete.apply(gURLBar);
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
gURLBar.onSearchComplete = function () {
|
||||
ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
|
||||
gURLBarOnSearchComplete.apply(gURLBar);
|
||||
resolve();
|
||||
}
|
||||
}).then(() => {
|
||||
// On Linux, the popup may or may not be open at this stage. So we need
|
||||
// additional checks to ensure we wait long enough.
|
||||
return promisePopupShown(gURLBar.popup);
|
||||
});
|
||||
}
|
||||
|
@ -155,7 +155,8 @@
|
||||
returnValue = action.params.url;
|
||||
break;
|
||||
}
|
||||
case "keyword": {
|
||||
case "keyword": // Fall through.
|
||||
case "searchengine": {
|
||||
returnValue = action.params.input;
|
||||
break;
|
||||
}
|
||||
@ -320,6 +321,12 @@
|
||||
return;
|
||||
} else if (action.type == "keyword") {
|
||||
url = action.params.url;
|
||||
} else if (action.type == "searchengine") {
|
||||
let engine = Services.search.getEngineByName(action.params.engineName);
|
||||
let submission = engine.getSubmission(action.params.searchQuery);
|
||||
|
||||
url = submission.uri.spec;
|
||||
postData = submission.postData;
|
||||
}
|
||||
}
|
||||
continueOperation.call(this);
|
||||
@ -1003,6 +1010,7 @@
|
||||
// Check for middle-click or modified clicks on the URL bar
|
||||
if (gURLBar && this.mInput == gURLBar) {
|
||||
var url = controller.getValueAt(this.selectedIndex);
|
||||
var options = {};
|
||||
|
||||
// close the autocomplete popup and revert the entered address
|
||||
this.closePopup();
|
||||
@ -1019,6 +1027,13 @@
|
||||
url = action.params.url;
|
||||
break;
|
||||
}
|
||||
case "searchengine": {
|
||||
let engine = Services.search.getEngineByName(action.params.engineName);
|
||||
let submission = engine.getSubmission(action.params.searchQuery);
|
||||
url = submission.uri.spec;
|
||||
options.postData = submission.postData;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
@ -1026,7 +1041,7 @@
|
||||
}
|
||||
|
||||
// respect the usual clicking subtleties
|
||||
openUILink(url, aEvent);
|
||||
openUILink(url, aEvent, options);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
|
@ -20,6 +20,9 @@ const LOOP_SESSION_TYPE = {
|
||||
FXA: 2,
|
||||
};
|
||||
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "loop.debug.loglevel";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
@ -30,9 +33,6 @@ Cu.importGlobalProperties(["URL"]);
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE"];
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
|
||||
"resource:///modules/loop/MozLoopAPI.jsm");
|
||||
|
||||
@ -67,6 +67,15 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
|
||||
"@mozilla.org/network/dns-service;1",
|
||||
"nsIDNSService");
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI;
|
||||
let consoleOptions = {
|
||||
maxLogLevel: Services.prefs.getCharPref(PREF_LOG_LEVEL).toLowerCase(),
|
||||
prefix: "Loop",
|
||||
};
|
||||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
// The current deferred for the registration process. This is set if in progress
|
||||
// or the registration was successful. This is null if a registration attempt was
|
||||
@ -112,7 +121,7 @@ CallProgressSocket.prototype = {
|
||||
connect: function(onSuccess, onError) {
|
||||
this._onSuccess = onSuccess;
|
||||
this._onError = onError ||
|
||||
(reason => {console.warn("MozLoopService::callProgessSocket - ", reason);});
|
||||
(reason => {log.warn("MozLoopService::callProgessSocket - ", reason);});
|
||||
|
||||
if (!onSuccess) {
|
||||
this._onError("missing onSuccess argument");
|
||||
@ -193,7 +202,7 @@ CallProgressSocket.prototype = {
|
||||
msg = JSON.parse(aMsg);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("MozLoopService: error parsing progress message - ", error);
|
||||
log.error("MozLoopService: error parsing progress message - ", error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -211,7 +220,7 @@ CallProgressSocket.prototype = {
|
||||
*/
|
||||
_send: function(aMsg) {
|
||||
if (!this._handshakeComplete) {
|
||||
console.warn("MozLoopService::_send error - handshake not complete");
|
||||
log.warn("MozLoopService::_send error - handshake not complete");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -316,6 +325,7 @@ let MozLoopServiceInternal = {
|
||||
},
|
||||
|
||||
notifyStatusChanged: function(aReason = null) {
|
||||
log.debug("notifyStatusChanged with reason:", aReason);
|
||||
Services.obs.notifyObservers(null, "loop-status-changed", aReason);
|
||||
},
|
||||
|
||||
@ -412,7 +422,7 @@ let MozLoopServiceInternal = {
|
||||
*/
|
||||
|
||||
_hawkRequestError: function(error) {
|
||||
console.error("Loop hawkRequest error:", error);
|
||||
log.error("Loop hawkRequest error:", error);
|
||||
throw error;
|
||||
},
|
||||
|
||||
@ -447,9 +457,10 @@ let MozLoopServiceInternal = {
|
||||
// XXX should do more validation here
|
||||
if (sessionToken.length === 64) {
|
||||
Services.prefs.setCharPref(this.getSessionTokenPrefName(sessionType), sessionToken);
|
||||
log.debug("Stored a hawk session token for sessionType", sessionType);
|
||||
} else {
|
||||
// XXX Bubble the precise details up to the UI somehow (bug 1013248).
|
||||
console.warn("Loop server sent an invalid session token");
|
||||
log.warn("Loop server sent an invalid session token");
|
||||
gRegisteredDeferred.reject("session-token-wrong-size");
|
||||
gRegisteredDeferred = null;
|
||||
return false;
|
||||
@ -470,6 +481,7 @@ let MozLoopServiceInternal = {
|
||||
*/
|
||||
clearSessionToken: function(sessionType) {
|
||||
Services.prefs.clearUserPref(this.getSessionTokenPrefName(sessionType));
|
||||
log.debug("Cleared hawk session token for sessionType", sessionType);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -494,7 +506,7 @@ let MozLoopServiceInternal = {
|
||||
// No need to clear the promise here, everything was good, so we don't need
|
||||
// to re-register.
|
||||
}, (error) => {
|
||||
console.error("Failed to register with Loop server: ", error);
|
||||
log.error("Failed to register with Loop server: ", error);
|
||||
gRegisteredDeferred.reject(error.errno);
|
||||
gRegisteredDeferred = null;
|
||||
});
|
||||
@ -517,6 +529,7 @@ let MozLoopServiceInternal = {
|
||||
if (!this.storeSessionToken(sessionType, response.headers))
|
||||
return;
|
||||
|
||||
log.debug("Successfully registered with server for sessionType", sessionType);
|
||||
this.clearError("registration");
|
||||
}, (error) => {
|
||||
// There's other errors than invalid auth token, but we should only do the reset
|
||||
@ -536,7 +549,7 @@ let MozLoopServiceInternal = {
|
||||
}
|
||||
|
||||
// XXX Bubble the precise details up to the UI somehow (bug 1013248).
|
||||
console.error("Failed to register with the loop server. Error: ", error);
|
||||
log.error("Failed to register with the loop server. Error: ", error);
|
||||
this.setError("registration", error);
|
||||
throw error;
|
||||
}
|
||||
@ -558,6 +571,7 @@ let MozLoopServiceInternal = {
|
||||
let unregisterURL = "/registration?simplePushURL=" + encodeURIComponent(pushURL);
|
||||
return this.hawkRequest(sessionType, unregisterURL, "DELETE")
|
||||
.then(() => {
|
||||
log.debug("Successfully unregistered from server for sessionType", sessionType);
|
||||
MozLoopServiceInternal.clearSessionToken(sessionType);
|
||||
},
|
||||
error => {
|
||||
@ -568,7 +582,7 @@ let MozLoopServiceInternal = {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error("Failed to unregister with the loop server. Error: ", error);
|
||||
log.error("Failed to unregister with the loop server. Error: ", error);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
@ -645,10 +659,10 @@ let MozLoopServiceInternal = {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn("Error: missing calls[] in response");
|
||||
log.warn("Error: missing calls[] in response");
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Error parsing calls info", err);
|
||||
log.warn("Error parsing calls info", err);
|
||||
}
|
||||
},
|
||||
|
||||
@ -760,7 +774,7 @@ let MozLoopServiceInternal = {
|
||||
|
||||
let worker = new ChromeWorker("MozLoopWorker.js");
|
||||
worker.onmessage = function(e) {
|
||||
console.log(e.data.ok ?
|
||||
log.info(e.data.ok ?
|
||||
"Successfully staged loop report for telemetry upload." :
|
||||
("Failed to stage loop report. Error: " + e.data.fail));
|
||||
}
|
||||
@ -898,7 +912,7 @@ let MozLoopServiceInternal = {
|
||||
client.launchWebFlow();
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
log.error(error);
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
@ -1068,7 +1082,7 @@ this.MozLoopService = {
|
||||
|
||||
if (now_serving > ticket) {
|
||||
// Hot diggity! It's our turn! Activate the service.
|
||||
console.log("MozLoopService: Activating Loop via soft-start");
|
||||
log.info("MozLoopService: Activating Loop via soft-start");
|
||||
Services.prefs.setBoolPref("loop.throttled", false);
|
||||
buttonNode.hidden = false;
|
||||
this.initialize();
|
||||
@ -1234,7 +1248,7 @@ this.MozLoopService = {
|
||||
try {
|
||||
Services.prefs.setCharPref("loop." + prefName, value);
|
||||
} catch (ex) {
|
||||
console.log("setLoopCharPref had trouble setting " + prefName +
|
||||
log.error("setLoopCharPref had trouble setting " + prefName +
|
||||
"; exception: " + ex);
|
||||
}
|
||||
},
|
||||
@ -1256,7 +1270,7 @@ this.MozLoopService = {
|
||||
try {
|
||||
return Services.prefs.getCharPref("loop." + prefName);
|
||||
} catch (ex) {
|
||||
console.log("getLoopCharPref had trouble getting " + prefName +
|
||||
log.error("getLoopCharPref had trouble getting " + prefName +
|
||||
"; exception: " + ex);
|
||||
return null;
|
||||
}
|
||||
@ -1279,7 +1293,7 @@ this.MozLoopService = {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("loop." + prefName);
|
||||
} catch (ex) {
|
||||
console.log("getLoopBoolPref had trouble getting " + prefName +
|
||||
log.error("getLoopBoolPref had trouble getting " + prefName +
|
||||
"; exception: " + ex);
|
||||
return null;
|
||||
}
|
||||
@ -1293,6 +1307,7 @@ this.MozLoopService = {
|
||||
* @return {Promise} that resolves when the FxA login flow is complete.
|
||||
*/
|
||||
logInToFxA: function() {
|
||||
log.debug("logInToFxA with gFxAOAuthTokenData:", !!gFxAOAuthTokenData);
|
||||
if (gFxAOAuthTokenData) {
|
||||
return Promise.resolve(gFxAOAuthTokenData);
|
||||
}
|
||||
@ -1320,7 +1335,7 @@ this.MozLoopService = {
|
||||
gFxAOAuthProfile = result;
|
||||
MozLoopServiceInternal.notifyStatusChanged("login");
|
||||
}, error => {
|
||||
console.error("Failed to retrieve profile", error);
|
||||
log.error("Failed to retrieve profile", error);
|
||||
gFxAOAuthProfile = null;
|
||||
MozLoopServiceInternal.notifyStatusChanged();
|
||||
});
|
||||
@ -1340,6 +1355,7 @@ this.MozLoopService = {
|
||||
* @return {Promise} that resolves when the FxA logout flow is complete.
|
||||
*/
|
||||
logOutFromFxA: Task.async(function*() {
|
||||
log.debug("logOutFromFxA");
|
||||
yield MozLoopServiceInternal.unregisterFromLoopServer(LOOP_SESSION_TYPE.FXA,
|
||||
gPushHandler.pushUrl);
|
||||
|
||||
|
@ -211,6 +211,7 @@
|
||||
@BINPATH@/components/dom_stylesheets.xpt
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_traversal.xpt
|
||||
@BINPATH@/components/dom_voicemail.xpt
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechrecognition.xpt
|
||||
#endif
|
||||
|
@ -76,7 +76,7 @@ OrganizerQueryAllBookmarks=All Bookmarks
|
||||
OrganizerQueryTags=Tags
|
||||
|
||||
# LOCALIZATION NOTE (tagResultLabel, bookmarkResultLabel, switchtabResultLabel,
|
||||
# keywordResultLabel)
|
||||
# keywordResultLabel, searchengineResultLabel)
|
||||
# Noun used to describe the location bar autocomplete result type
|
||||
# to users with screen readers
|
||||
# See createResultLabel() in urlbarBindings.xml
|
||||
@ -84,6 +84,8 @@ tagResultLabel=Tag
|
||||
bookmarkResultLabel=Bookmark
|
||||
switchtabResultLabel=Tab
|
||||
keywordResultLabel=Keyword
|
||||
searchengineResultLabel=Search
|
||||
|
||||
|
||||
# LOCALIZATION NOTE (lockPrompt.text)
|
||||
# %S will be replaced with the application name.
|
||||
|
@ -1505,6 +1505,14 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
|
||||
}
|
||||
|
||||
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
|
||||
color: GrayText;
|
||||
}
|
||||
|
@ -2218,6 +2218,14 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
|
||||
-moz-image-region: rect(11px, 16px, 22px, 0);
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.ac-result-type-bookmark {
|
||||
list-style-image: url("chrome://browser/skin/places/star-icons@2x.png");
|
||||
|
@ -135,6 +135,7 @@
|
||||
}
|
||||
|
||||
/* TITLES */
|
||||
#newtab-intro-what,
|
||||
.newtab-sponsored,
|
||||
.newtab-title {
|
||||
color: #5c5c5c;
|
||||
|
@ -1463,6 +1463,20 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
%endif
|
||||
|
||||
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
|
||||
}
|
||||
|
||||
%ifdef WINDOWS_AERO
|
||||
@media not all and (-moz-windows-default-theme) {
|
||||
%endif
|
||||
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
|
||||
}
|
||||
%ifdef WINDOWS_AERO
|
||||
}
|
||||
%endif
|
||||
|
||||
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
|
||||
color: GrayText;
|
||||
}
|
||||
|
@ -6221,13 +6221,13 @@ if test "$OS_ARCH" = "WINNT"; then
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
if test -z "$CROSS_COMPILE"; then
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $REQ_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
|
||||
else
|
||||
MAKENSISU=
|
||||
fi
|
||||
fi
|
||||
elif test -z "$CROSS_COMPILE"; then
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $REQ_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
|
||||
else
|
||||
MAKENSISU=
|
||||
fi
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "mozilla/dom/MobileMessageManager.h"
|
||||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||
#include "mozilla/dom/Telephony.h"
|
||||
#include "mozilla/dom/Voicemail.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "nsISiteSpecificUserAgent.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
@ -50,7 +51,6 @@
|
||||
#include "mozilla/dom/IccManager.h"
|
||||
#include "mozilla/dom/CellBroadcast.h"
|
||||
#include "mozilla/dom/MobileConnectionArray.h"
|
||||
#include "mozilla/dom/Voicemail.h"
|
||||
#endif
|
||||
#include "nsIIdleObserver.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
@ -175,12 +175,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBluetooth)
|
||||
@ -251,6 +251,11 @@ Navigator::Invalidate()
|
||||
mTelephony = nullptr;
|
||||
}
|
||||
|
||||
if (mVoicemail) {
|
||||
mVoicemail->Shutdown();
|
||||
mVoicemail = nullptr;
|
||||
}
|
||||
|
||||
if (mConnection) {
|
||||
mConnection->Shutdown();
|
||||
mConnection = nullptr;
|
||||
@ -269,10 +274,6 @@ Navigator::Invalidate()
|
||||
mIccManager->Shutdown();
|
||||
mIccManager = nullptr;
|
||||
}
|
||||
|
||||
if (mVoicemail) {
|
||||
mVoicemail = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
@ -1651,6 +1652,8 @@ Navigator::GetMozCellBroadcast(ErrorResult& aRv)
|
||||
return mCellBroadcast;
|
||||
}
|
||||
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
Voicemail*
|
||||
Navigator::GetMozVoicemail(ErrorResult& aRv)
|
||||
{
|
||||
@ -1660,15 +1663,14 @@ Navigator::GetMozVoicemail(ErrorResult& aRv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aRv = NS_NewVoicemail(mWindow, getter_AddRefs(mVoicemail));
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
mVoicemail = Voicemail::Create(mWindow, aRv);
|
||||
}
|
||||
|
||||
return mVoicemail;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
||||
IccManager*
|
||||
Navigator::GetMozIccManager(ErrorResult& aRv)
|
||||
{
|
||||
|
@ -88,11 +88,11 @@ class BluetoothManager;
|
||||
class CellBroadcast;
|
||||
class IccManager;
|
||||
class MobileConnectionArray;
|
||||
class Voicemail;
|
||||
#endif
|
||||
|
||||
class PowerManager;
|
||||
class Telephony;
|
||||
class Voicemail;
|
||||
|
||||
namespace time {
|
||||
class TimeManager;
|
||||
@ -221,6 +221,7 @@ public:
|
||||
DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
|
||||
MobileMessageManager* GetMozMobileMessage();
|
||||
Telephony* GetMozTelephony(ErrorResult& aRv);
|
||||
Voicemail* GetMozVoicemail(ErrorResult& aRv);
|
||||
network::Connection* GetConnection(ErrorResult& aRv);
|
||||
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
|
||||
void MozSetMessageHandler(const nsAString& aType,
|
||||
@ -234,7 +235,6 @@ public:
|
||||
#ifdef MOZ_B2G_RIL
|
||||
MobileConnectionArray* GetMozMobileConnections(ErrorResult& aRv);
|
||||
CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
|
||||
Voicemail* GetMozVoicemail(ErrorResult& aRv);
|
||||
IccManager* GetMozIccManager(ErrorResult& aRv);
|
||||
#endif // MOZ_B2G_RIL
|
||||
#ifdef MOZ_GAMEPAD
|
||||
@ -331,12 +331,12 @@ private:
|
||||
nsRefPtr<PowerManager> mPowerManager;
|
||||
nsRefPtr<MobileMessageManager> mMobileMessageManager;
|
||||
nsRefPtr<Telephony> mTelephony;
|
||||
nsRefPtr<Voicemail> mVoicemail;
|
||||
nsRefPtr<network::Connection> mConnection;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsRefPtr<MobileConnectionArray> mMobileConnections;
|
||||
nsRefPtr<CellBroadcast> mCellBroadcast;
|
||||
nsRefPtr<IccManager> mIccManager;
|
||||
nsRefPtr<Voicemail> mVoicemail;
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
nsRefPtr<bluetooth::BluetoothManager> mBluetooth;
|
||||
|
@ -755,6 +755,10 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::Voicemail',
|
||||
},
|
||||
|
||||
'MozVoicemailStatus': {
|
||||
'nativeType': 'mozilla::dom::VoicemailStatus',
|
||||
},
|
||||
|
||||
'MutationObserver': {
|
||||
'nativeType': 'nsDOMMutationObserver',
|
||||
},
|
||||
|
@ -188,6 +188,12 @@ extern bool gBluetoothDebugFlag;
|
||||
// Bluetooth stack internal error, such as I/O error
|
||||
#define ERR_INTERNAL_ERROR "InternalError"
|
||||
|
||||
/**
|
||||
* BT specification v4.1 defines the maximum attribute length as 512 octets.
|
||||
* Currently use 600 here to conform to bluedroid's BTGATT_MAX_ATTR_LEN.
|
||||
*/
|
||||
#define BLUETOOTH_GATT_MAX_ATTR_LEN 600
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
enum BluetoothStatus {
|
||||
@ -497,6 +503,46 @@ struct BluetoothAvrcpPlayerSettings {
|
||||
uint8_t mValues[256];
|
||||
};
|
||||
|
||||
struct BluetoothGattAdvData {
|
||||
uint8_t mAdvData[62];
|
||||
};
|
||||
|
||||
struct BluetoothGattId {
|
||||
BluetoothUuid mUuid;
|
||||
uint8_t mInstanceId;
|
||||
};
|
||||
|
||||
struct BluetoothGattServiceId {
|
||||
BluetoothGattId mId;
|
||||
uint8_t mIsPrimary;
|
||||
};
|
||||
|
||||
struct BluetoothGattReadParam {
|
||||
BluetoothGattServiceId mServiceId;
|
||||
BluetoothGattId mCharId;
|
||||
BluetoothGattId mDescriptorId;
|
||||
uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN];
|
||||
uint16_t mValueLength;
|
||||
uint16_t mValueType;
|
||||
uint8_t mStatus;
|
||||
};
|
||||
|
||||
struct BluetoothGattWriteParam {
|
||||
BluetoothGattServiceId mServiceId;
|
||||
BluetoothGattId mCharId;
|
||||
BluetoothGattId mDescriptorId;
|
||||
uint8_t mStatus;
|
||||
};
|
||||
|
||||
struct BluetoothGattNotifyParam {
|
||||
uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN];
|
||||
nsString mBdAddr;
|
||||
BluetoothGattServiceId mServiceId;
|
||||
BluetoothGattId mCharId;
|
||||
uint16_t mLength;
|
||||
uint8_t mIsNotify;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_bluetooth_bluetoothcommon_h__
|
||||
|
@ -76,6 +76,41 @@ BluetoothAvrcpInterface::BluetoothAvrcpInterface()
|
||||
BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
|
||||
{ }
|
||||
|
||||
//
|
||||
// Bluetooth GATT Interface
|
||||
//
|
||||
|
||||
// Notification handling
|
||||
//
|
||||
|
||||
BluetoothGattClientNotificationHandler::~BluetoothGattClientNotificationHandler()
|
||||
{ }
|
||||
|
||||
BluetoothGattServerNotificationHandler::~BluetoothGattServerNotificationHandler()
|
||||
{ }
|
||||
|
||||
BluetoothGattNotificationHandler::~BluetoothGattNotificationHandler()
|
||||
{ }
|
||||
|
||||
// Interface
|
||||
//
|
||||
|
||||
BluetoothGattClientInterface::BluetoothGattClientInterface()
|
||||
{ }
|
||||
|
||||
BluetoothGattClientInterface::~BluetoothGattClientInterface()
|
||||
{ }
|
||||
|
||||
BluetoothGattInterface::BluetoothGattInterface()
|
||||
{ }
|
||||
|
||||
BluetoothGattInterface::~BluetoothGattInterface()
|
||||
{ }
|
||||
|
||||
//
|
||||
// Bluetooth Core Interface
|
||||
//
|
||||
|
||||
// Notification handling
|
||||
//
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
@ -452,6 +453,351 @@ protected:
|
||||
virtual ~BluetoothAvrcpInterface();
|
||||
};
|
||||
|
||||
//
|
||||
// GATT Interface
|
||||
//
|
||||
|
||||
class BluetoothGattClientNotificationHandler
|
||||
{
|
||||
public:
|
||||
virtual ~BluetoothGattClientNotificationHandler();
|
||||
|
||||
virtual void
|
||||
RegisterClientNotification(int aStatus,
|
||||
int aClientIf,
|
||||
const BluetoothUuid& aAppUuid)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ScanResultNotification(const nsAString& aBdAddr,
|
||||
int aRssi,
|
||||
const BluetoothGattAdvData& aAdvData)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ConnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
DisconnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
SearchCompleteNotification(int aConnId, int aStatus) { }
|
||||
virtual void
|
||||
SearchResultNotification(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
GetCharacteristicNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aCharProperty)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
GetDescriptorNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
GetIncludedServiceNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattServiceId& aIncludedServId)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
RegisterNotificationNotification(int aConnId,
|
||||
int aIsRegister,
|
||||
int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
NotifyNotification(int aConnId, const BluetoothGattNotifyParam& aNotifyParam)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ReadCharacteristicNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattReadParam& aReadParam)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
WriteCharacteristicNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattWriteParam& aWriteParam)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ReadDescriptorNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattReadParam& aReadParam)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
WriteDescriptorNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattWriteParam& aWriteParam)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ExecuteWriteNotification(int aConnId, int aStatus) { }
|
||||
|
||||
virtual void
|
||||
ReadRemoteRssiNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aRssi,
|
||||
int aStatus)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ListenNotification(int aStatus, int aServerIf) { }
|
||||
|
||||
protected:
|
||||
BluetoothGattClientNotificationHandler()
|
||||
{ }
|
||||
};
|
||||
|
||||
class BluetoothGattServerNotificationHandler
|
||||
{
|
||||
public:
|
||||
virtual ~BluetoothGattServerNotificationHandler();
|
||||
// TODO: Add server notifications
|
||||
|
||||
protected:
|
||||
BluetoothGattServerNotificationHandler()
|
||||
{ }
|
||||
};
|
||||
|
||||
class BluetoothGattNotificationHandler
|
||||
: public BluetoothGattClientNotificationHandler
|
||||
, public BluetoothGattServerNotificationHandler
|
||||
{
|
||||
public:
|
||||
virtual ~BluetoothGattNotificationHandler();
|
||||
|
||||
protected:
|
||||
BluetoothGattNotificationHandler()
|
||||
{ }
|
||||
};
|
||||
|
||||
class BluetoothGattClientResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothGattClientResultHandler)
|
||||
|
||||
virtual ~BluetoothGattClientResultHandler() { }
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
}
|
||||
|
||||
virtual void RegisterClient() { }
|
||||
virtual void UnregisterClient() { }
|
||||
|
||||
virtual void Scan() { }
|
||||
|
||||
virtual void Connect() { }
|
||||
virtual void Disconnect() { }
|
||||
|
||||
virtual void Listen() { }
|
||||
virtual void Refresh() { }
|
||||
|
||||
virtual void SearchService() { }
|
||||
virtual void GetIncludedService() { }
|
||||
virtual void GetCharacteristic() { }
|
||||
virtual void GetDescriptor() { }
|
||||
|
||||
virtual void ReadCharacteristic() { }
|
||||
virtual void WriteCharacteristic() { }
|
||||
virtual void ReadDescriptor() { }
|
||||
virtual void WriteDescriptor() { }
|
||||
|
||||
virtual void ExecuteWrite() { }
|
||||
|
||||
virtual void RegisterNotification() { }
|
||||
virtual void DeregisterNotification() { }
|
||||
|
||||
virtual void ReadRemoteRssi() { }
|
||||
virtual void GetDeviceType() { }
|
||||
virtual void SetAdvData() { }
|
||||
};
|
||||
|
||||
// TODO: Add GattServerResultHandler
|
||||
|
||||
class BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothGattResultHandler)
|
||||
|
||||
virtual ~BluetoothGattResultHandler() { }
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
}
|
||||
|
||||
virtual void Init() { }
|
||||
virtual void Cleanup() { }
|
||||
};
|
||||
|
||||
class BluetoothGattClientInterface
|
||||
{
|
||||
public:
|
||||
/* Register / Unregister */
|
||||
virtual void RegisterClient(const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void UnregisterClient(int aClientIf,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Start / Stop LE Scan */
|
||||
virtual void Scan(int aClientIf, bool aStart,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Connect / Disconnect */
|
||||
virtual void Connect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void Disconnect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Start / Stop advertisements to listen for incoming connections */
|
||||
virtual void Listen(int aClientIf,
|
||||
bool aIsStart,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Clear the attribute cache for a given device*/
|
||||
virtual void Refresh(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Enumerate Attributes */
|
||||
virtual void SearchService(int aConnId,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void GetIncludedService(
|
||||
int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattServiceId& aStartServiceId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void GetCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aStartCharId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void GetDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Read / Write An Attribute */
|
||||
virtual void ReadCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void WriteCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void ReadDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
virtual void ExecuteWrite(int aConnId,
|
||||
int aIsExecute,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
|
||||
/* Register / Deregister Characteristic Notifications or Indications */
|
||||
virtual void RegisterNotification(
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
virtual void DeregisterNotification(
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
virtual void ReadRemoteRssi(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
virtual void GetDeviceType(const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
/* Set advertising data or scan response data */
|
||||
virtual void SetAdvData(int aServerIf,
|
||||
bool aIsScanRsp,
|
||||
bool aIsNameIncluded,
|
||||
bool aIsTxPowerIncluded,
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint8_t aManufacturerLen,
|
||||
const ArrayBuffer& aManufacturerData,
|
||||
BluetoothGattClientResultHandler* aRes) = 0;
|
||||
|
||||
protected:
|
||||
BluetoothGattClientInterface();
|
||||
virtual ~BluetoothGattClientInterface();
|
||||
};
|
||||
|
||||
// TODO: Add GattServerInterface
|
||||
|
||||
class BluetoothGattInterface
|
||||
{
|
||||
public:
|
||||
virtual void Init(BluetoothGattNotificationHandler* aNotificationHandler,
|
||||
BluetoothGattResultHandler* aRes) = 0;
|
||||
virtual void Cleanup(BluetoothGattResultHandler* aRes) = 0;
|
||||
|
||||
virtual BluetoothGattClientInterface* GetBluetoothGattClientInterface() = 0;
|
||||
|
||||
protected:
|
||||
BluetoothGattInterface();
|
||||
virtual ~BluetoothGattInterface();
|
||||
};
|
||||
|
||||
//
|
||||
// Bluetooth Core Interface
|
||||
//
|
||||
@ -625,6 +971,7 @@ public:
|
||||
virtual BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() = 0;
|
||||
virtual BluetoothA2dpInterface* GetBluetoothA2dpInterface() = 0;
|
||||
virtual BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() = 0;
|
||||
virtual BluetoothGattInterface* GetBluetoothGattInterface() = 0;
|
||||
|
||||
protected:
|
||||
BluetoothInterface();
|
||||
|
1149
dom/bluetooth2/bluedroid/BluetoothGattHALInterface.cpp
Normal file
1149
dom/bluetooth2/bluedroid/BluetoothGattHALInterface.cpp
Normal file
File diff suppressed because it is too large
Load Diff
186
dom/bluetooth2/bluedroid/BluetoothGattHALInterface.h
Normal file
186
dom/bluetooth2/bluedroid/BluetoothGattHALInterface.h
Normal file
@ -0,0 +1,186 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothgatthalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothgatthalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#if ANDROID_VERSION >= 19
|
||||
#include <hardware/bt_gatt.h>
|
||||
#endif
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothGattClientHALInterface MOZ_FINAL
|
||||
: public BluetoothGattClientInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothGattHALInterface;
|
||||
|
||||
/* Register / Unregister */
|
||||
void RegisterClient(const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void UnregisterClient(int aClientIf,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Start / Stop LE Scan */
|
||||
void Scan(int aClientIf, bool aStart,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Connect / Disconnect */
|
||||
void Connect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void Disconnect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Start / Stop advertisements to listen for incoming connections */
|
||||
void Listen(int aClientIf,
|
||||
bool aIsStart,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Clear the attribute cache for a given device*/
|
||||
void Refresh(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Enumerate Attributes */
|
||||
void SearchService(int aConnId,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetIncludedService(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattServiceId& aStartServiceId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aStartCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Read / Write An Attribute */
|
||||
void ReadCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void WriteCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void ReadDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
int aWriteType,
|
||||
int aLen,
|
||||
int aAuthReq,
|
||||
const ArrayBuffer& aValue,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
void ExecuteWrite(int aConnId,
|
||||
int aIsExecute,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
|
||||
/* Register / Deregister Characteristic Notifications or Indications */
|
||||
void RegisterNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void DeregisterNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
void ReadRemoteRssi(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
void GetDeviceType(const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Set advertising data or scan response data */
|
||||
void SetAdvData(int aServerIf,
|
||||
bool aIsScanRsp,
|
||||
bool aIsNameIncluded,
|
||||
bool aIsTxPowerIncluded,
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint8_t aManufacturerLen,
|
||||
const ArrayBuffer& aManufacturerData,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothGattClientHALInterface(
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_client_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothGattClientHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_client_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
// TODO: Add server interface
|
||||
|
||||
class BluetoothGattHALInterface MOZ_FINAL
|
||||
: public BluetoothGattInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Init(BluetoothGattNotificationHandler* aNotificationHandler,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
void Cleanup(BluetoothGattResultHandler* aRes);
|
||||
|
||||
BluetoothGattClientInterface* GetBluetoothGattClientInterface();
|
||||
|
||||
protected:
|
||||
BluetoothGattHALInterface(
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothGattHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
321
dom/bluetooth2/bluedroid/BluetoothGattManager.cpp
Normal file
321
dom/bluetooth2/bluedroid/BluetoothGattManager.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothGattManager.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
namespace {
|
||||
StaticRefPtr<BluetoothGattManager> sBluetoothGattManager;
|
||||
static BluetoothGattInterface* sBluetoothGattInterface;
|
||||
static BluetoothGattClientInterface* sBluetoothGattClientInterface;
|
||||
} // anonymous namespace
|
||||
|
||||
bool BluetoothGattManager::mInShutdown = false;
|
||||
|
||||
/*
|
||||
* Static functions
|
||||
*/
|
||||
|
||||
BluetoothGattManager*
|
||||
BluetoothGattManager::Get()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If sBluetoothGattManager already exists, exit early
|
||||
if (sBluetoothGattManager) {
|
||||
return sBluetoothGattManager;
|
||||
}
|
||||
|
||||
// If we're in shutdown, don't create a new instance
|
||||
NS_ENSURE_FALSE(mInShutdown, nullptr);
|
||||
|
||||
// Create a new instance, register, and return
|
||||
BluetoothGattManager* manager = new BluetoothGattManager();
|
||||
sBluetoothGattManager = manager;
|
||||
return sBluetoothGattManager;
|
||||
}
|
||||
|
||||
class InitGattResultHandler MOZ_FINAL : public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
InitGattResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothGattInterface::Init failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() MOZ_OVERRIDE
|
||||
{
|
||||
if (mRes) {
|
||||
mRes->Init();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
// static
|
||||
void
|
||||
BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
{
|
||||
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
|
||||
if (!btInf) {
|
||||
BT_LOGR("Error: Bluetooth interface not available");
|
||||
if (aRes) {
|
||||
aRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sBluetoothGattInterface = btInf->GetBluetoothGattInterface();
|
||||
if (!sBluetoothGattInterface) {
|
||||
BT_LOGR("Error: Bluetooth GATT interface not available");
|
||||
if (aRes) {
|
||||
aRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sBluetoothGattClientInterface =
|
||||
sBluetoothGattInterface->GetBluetoothGattClientInterface();
|
||||
NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface);
|
||||
|
||||
BluetoothGattManager* gattManager = BluetoothGattManager::Get();
|
||||
sBluetoothGattInterface->Init(gattManager,
|
||||
new InitGattResultHandler(aRes));
|
||||
}
|
||||
|
||||
class CleanupResultHandler MOZ_FINAL : public BluetoothGattResultHandler
|
||||
{
|
||||
public:
|
||||
CleanupResultHandler(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{ }
|
||||
|
||||
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
|
||||
{
|
||||
BT_WARNING("BluetoothGattInterface::Cleanup failed: %d",
|
||||
(int)aStatus);
|
||||
if (mRes) {
|
||||
mRes->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup() MOZ_OVERRIDE
|
||||
{
|
||||
sBluetoothGattClientInterface = nullptr;
|
||||
sBluetoothGattInterface = nullptr;
|
||||
if (mRes) {
|
||||
mRes->Deinit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
class CleanupResultHandlerRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
CleanupResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
||||
: mRes(aRes)
|
||||
{
|
||||
MOZ_ASSERT(mRes);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
mRes->Deinit();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||
};
|
||||
|
||||
// static
|
||||
void
|
||||
BluetoothGattManager::DeinitGattInterface(BluetoothProfileResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sBluetoothGattInterface) {
|
||||
sBluetoothGattInterface->Cleanup(new CleanupResultHandler(aRes));
|
||||
} else if (aRes) {
|
||||
// We dispatch a runnable here to make the profile resource handler
|
||||
// behave as if GATT was initialized.
|
||||
nsRefPtr<nsRunnable> r = new CleanupResultHandlerRunnable(aRes);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Notification Handlers
|
||||
//
|
||||
void
|
||||
BluetoothGattManager::RegisterClientNotification(int aStatus,
|
||||
int aClientIf,
|
||||
const BluetoothUuid& aAppUuid)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ScanResultNotification(
|
||||
const nsAString& aBdAddr, int aRssi,
|
||||
const BluetoothGattAdvData& aAdvData)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ConnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::DisconnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::SearchCompleteNotification(int aConnId, int aStatus)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::SearchResultNotification(
|
||||
int aConnId, const BluetoothGattServiceId& aServiceId)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::GetCharacteristicNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aCharProperty)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::GetDescriptorNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::GetIncludedServiceNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattServiceId& aIncludedServId)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::RegisterNotificationNotification(
|
||||
int aConnId, int aIsRegister, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::NotifyNotification(
|
||||
int aConnId, const BluetoothGattNotifyParam& aNotifyParam)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ReadCharacteristicNotification(
|
||||
int aConnId, int aStatus, const BluetoothGattReadParam& aReadParam)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::WriteCharacteristicNotification(
|
||||
int aConnId, int aStatus, const BluetoothGattWriteParam& aWriteParam)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ReadDescriptorNotification(
|
||||
int aConnId, int aStatus, const BluetoothGattReadParam& aReadParam)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::WriteDescriptorNotification(
|
||||
int aConnId, int aStatus, const BluetoothGattWriteParam& aWriteParam)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ExecuteWriteNotification(int aConnId, int aStatus)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aRssi,
|
||||
int aStatus)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothGattManager::ListenNotification(int aStatus,
|
||||
int aServerIf)
|
||||
{ }
|
||||
|
||||
BluetoothGattManager::BluetoothGattManager()
|
||||
{ }
|
||||
|
||||
BluetoothGattManager::~BluetoothGattManager()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
||||
BT_WARNING("Failed to remove shutdown observer!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothGattManager::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothGattManager);
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
HandleShutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "BluetoothGattManager got unexpected topic!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothGattManager::HandleShutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInShutdown = true;
|
||||
sBluetoothGattManager = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BluetoothGattManager, nsIObserver)
|
115
dom/bluetooth2/bluedroid/BluetoothGattManager.h
Normal file
115
dom/bluetooth2/bluedroid/BluetoothGattManager.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothgattmanager_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothgattmanager_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
class BluetoothGattManager MOZ_FINAL : public nsIObserver
|
||||
, public BluetoothGattNotificationHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static BluetoothGattManager* Get();
|
||||
static void InitGattInterface(BluetoothProfileResultHandler* aRes);
|
||||
static void DeinitGattInterface(BluetoothProfileResultHandler* aRes);
|
||||
virtual ~BluetoothGattManager();
|
||||
|
||||
private:
|
||||
BluetoothGattManager();
|
||||
|
||||
void HandleShutdown();
|
||||
|
||||
void RegisterClientNotification(int aStatus,
|
||||
int aClientIf,
|
||||
const BluetoothUuid& aAppUuid) MOZ_OVERRIDE;
|
||||
|
||||
void ScanResultNotification(
|
||||
const nsAString& aBdAddr, int aRssi,
|
||||
const BluetoothGattAdvData& aAdvData) MOZ_OVERRIDE;
|
||||
|
||||
void ConnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr) MOZ_OVERRIDE;
|
||||
|
||||
void DisconnectNotification(int aConnId,
|
||||
int aStatus,
|
||||
int aClientIf,
|
||||
const nsAString& aBdAddr) MOZ_OVERRIDE;
|
||||
|
||||
void SearchCompleteNotification(int aConnId, int aStatus) MOZ_OVERRIDE;
|
||||
|
||||
void SearchResultNotification(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
void GetCharacteristicNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
int aCharProperty) MOZ_OVERRIDE;
|
||||
|
||||
void GetDescriptorNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId) MOZ_OVERRIDE;
|
||||
|
||||
void GetIncludedServiceNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattServiceId& aIncludedServId) MOZ_OVERRIDE;
|
||||
|
||||
void RegisterNotificationNotification(
|
||||
int aConnId, int aIsRegister, int aStatus,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId) MOZ_OVERRIDE;
|
||||
|
||||
void NotifyNotification(int aConnId,
|
||||
const BluetoothGattNotifyParam& aNotifyParam)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
void ReadCharacteristicNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattReadParam& aReadParam)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
void WriteCharacteristicNotification(
|
||||
int aConnId, int aStatus,
|
||||
const BluetoothGattWriteParam& aWriteParam) MOZ_OVERRIDE;
|
||||
|
||||
void ReadDescriptorNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattReadParam& aReadParam)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
void WriteDescriptorNotification(int aConnId,
|
||||
int aStatus,
|
||||
const BluetoothGattWriteParam& aWriteParam)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
void ExecuteWriteNotification(int aConnId, int aStatus) MOZ_OVERRIDE;
|
||||
|
||||
void ReadRemoteRssiNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aRssi,
|
||||
int aStatus) MOZ_OVERRIDE;
|
||||
|
||||
void ListenNotification(int aStatus, int aServerIf) MOZ_OVERRIDE;
|
||||
|
||||
static bool mInShutdown;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -122,6 +122,18 @@ Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothUuid& aIn, bt_uuid_t& aOut)
|
||||
{
|
||||
if (sizeof(aIn.mUuid) != sizeof(aOut.uu)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memcpy(aOut.uu, aIn.mUuid, sizeof(aOut.uu));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, bt_pin_code_t& aOut)
|
||||
{
|
||||
@ -211,6 +223,112 @@ Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut)
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 18
|
||||
|
||||
nsresult
|
||||
Convert(const uint8_t* aIn, BluetoothGattAdvData& aOut)
|
||||
{
|
||||
memcpy(aOut.mAdvData, aIn, sizeof(aOut.mAdvData));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
nsresult
|
||||
Convert(const BluetoothGattId& aIn, btgatt_gatt_id_t& aOut)
|
||||
{
|
||||
aOut.inst_id = aIn.mInstanceId;
|
||||
return Convert(aIn.mUuid, aOut.uuid);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_gatt_id_t& aIn, BluetoothGattId& aOut)
|
||||
{
|
||||
aOut.mInstanceId = aIn.inst_id;
|
||||
return Convert(aIn.uuid, aOut.mUuid);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothGattServiceId& aIn, btgatt_srvc_id_t& aOut)
|
||||
{
|
||||
aOut.is_primary = aIn.mIsPrimary;
|
||||
return Convert(aIn.mId, aOut.id);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_srvc_id_t& aIn, BluetoothGattServiceId& aOut)
|
||||
{
|
||||
aOut.mIsPrimary = aIn.is_primary;
|
||||
return Convert(aIn.id, aOut.mId);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_read_params_t& aIn, BluetoothGattReadParam& aOut)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.descr_id, aOut.mDescriptorId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
memcpy(aOut.mValue, aIn.value.value, aIn.value.len);
|
||||
aOut.mValueLength = aIn.value.len;
|
||||
aOut.mValueType = aIn.value_type;
|
||||
aOut.mStatus = aIn.status;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_write_params_t& aIn, BluetoothGattWriteParam& aOut)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.descr_id, aOut.mDescriptorId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aOut.mStatus = aIn.status;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_notify_params_t& aIn, BluetoothGattNotifyParam& aOut)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = Convert(aIn.bda, aOut.mBdAddr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
memcpy(aOut.mValue, aIn.value, aIn.len);
|
||||
aOut.mLength = aIn.len;
|
||||
aOut.mIsNotify = aIn.is_notify;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 19
|
||||
|
||||
nsresult
|
||||
Convert(const ArrayBuffer& aIn, char* aOut) {
|
||||
aIn.ComputeLengthAndData();
|
||||
memcpy(aOut, aIn.Data(), aIn.Length());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
|
||||
{
|
||||
|
@ -14,9 +14,13 @@
|
||||
#if ANDROID_VERSION >= 18
|
||||
#include <hardware/bt_rc.h>
|
||||
#endif
|
||||
#if ANDROID_VERSION >= 19
|
||||
#include <hardware/bt_gatt.h>
|
||||
#endif
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
@ -141,6 +145,9 @@ Convert(const uint8_t aIn[16], bt_uuid_t& aOut);
|
||||
nsresult
|
||||
Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothUuid& aIn, bt_uuid_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, bt_pin_code_t& aOut);
|
||||
|
||||
@ -754,6 +761,35 @@ Convert(btrc_remote_features_t aIn, unsigned long& aOut)
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 19
|
||||
|
||||
nsresult
|
||||
Convert(const uint8_t* aIn, BluetoothGattAdvData& aOut);
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
nsresult
|
||||
Convert(const BluetoothGattId& aIn, btgatt_gatt_id_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_gatt_id_t& aIn, BluetoothGattId& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothGattServiceId& aIn, btgatt_srvc_id_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_srvc_id_t& aIn, BluetoothGattServiceId& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_read_params_t& aIn, BluetoothGattReadParam& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_write_params_t& aIn, BluetoothGattWriteParam& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_notify_params_t& aIn, BluetoothGattNotifyParam& aOut);
|
||||
#endif // ANDROID_VERSION >= 19
|
||||
|
||||
nsresult
|
||||
Convert(const ArrayBuffer& aIn, char* aOut);
|
||||
|
||||
/* |ConvertArray| is a helper for converting arrays. Pass an
|
||||
* instance of this structure as the first argument to |Convert|
|
||||
* to convert an array. The output type has to support the array
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "BluetoothHALHelpers.h"
|
||||
#include "BluetoothA2dpHALInterface.h"
|
||||
#include "BluetoothAvrcpHALInterface.h"
|
||||
#include "BluetoothGattHALInterface.h"
|
||||
#include "BluetoothHandsfreeHALInterface.h"
|
||||
#include "BluetoothSocketHALInterface.h"
|
||||
|
||||
@ -63,6 +64,19 @@ struct interface_traits<BluetoothAvrcpHALInterface>
|
||||
};
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
template<>
|
||||
struct interface_traits<BluetoothGattHALInterface>
|
||||
{
|
||||
typedef const btgatt_interface_t const_interface_type;
|
||||
|
||||
static const char* profile_id()
|
||||
{
|
||||
return BT_PROFILE_GATT_ID;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable0<BluetoothResultHandler, void>
|
||||
BluetoothHALResultRunnable;
|
||||
@ -873,6 +887,22 @@ BluetoothHALInterface::CreateProfileInterface<BluetoothAvrcpHALInterface>()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION < 19
|
||||
/*
|
||||
* Versions that we don't support GATT will call this function
|
||||
* to create an GATT interface. All interface methods will fail with
|
||||
* the error constant STATUS_UNSUPPORTED.
|
||||
*/
|
||||
template <>
|
||||
BluetoothGattHALInterface*
|
||||
BluetoothHALInterface::CreateProfileInterface<BluetoothGattHALInterface>()
|
||||
{
|
||||
BT_WARNING("Bluetooth profile 'gatt' is not supported");
|
||||
|
||||
return new BluetoothGattHALInterface();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
BluetoothHALInterface::GetProfileInterface()
|
||||
@ -912,4 +942,10 @@ BluetoothHALInterface::GetBluetoothAvrcpInterface()
|
||||
return GetProfileInterface<BluetoothAvrcpHALInterface>();
|
||||
}
|
||||
|
||||
BluetoothGattInterface*
|
||||
BluetoothHALInterface::GetBluetoothGattInterface()
|
||||
{
|
||||
return GetProfileInterface<BluetoothGattHALInterface>();
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface();
|
||||
BluetoothA2dpInterface* GetBluetoothA2dpInterface();
|
||||
BluetoothAvrcpInterface* GetBluetoothAvrcpInterface();
|
||||
BluetoothGattInterface* GetBluetoothGattInterface();
|
||||
|
||||
protected:
|
||||
BluetoothHALInterface(const bt_interface_t* aInterface);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
|
||||
#include "BluetoothA2dpManager.h"
|
||||
#include "BluetoothGattManager.h"
|
||||
#include "BluetoothHfpManager.h"
|
||||
#include "BluetoothOppManager.h"
|
||||
#include "BluetoothProfileController.h"
|
||||
@ -167,7 +168,8 @@ public:
|
||||
{
|
||||
static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
|
||||
BluetoothHfpManager::DeinitHfpInterface,
|
||||
BluetoothA2dpManager::DeinitA2dpInterface
|
||||
BluetoothA2dpManager::DeinitA2dpInterface,
|
||||
BluetoothGattManager::DeinitGattInterface
|
||||
};
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -304,7 +306,8 @@ public:
|
||||
{
|
||||
static void (* const sInitManager[])(BluetoothProfileResultHandler*) = {
|
||||
BluetoothHfpManager::InitHfpInterface,
|
||||
BluetoothA2dpManager::InitA2dpInterface
|
||||
BluetoothA2dpManager::InitA2dpInterface,
|
||||
BluetoothGattManager::InitGattInterface
|
||||
};
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -51,6 +51,8 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluedroid/BluetoothA2dpHALInterface.cpp',
|
||||
'bluedroid/BluetoothA2dpManager.cpp',
|
||||
'bluedroid/BluetoothAvrcpHALInterface.cpp',
|
||||
'bluedroid/BluetoothGattHALInterface.cpp',
|
||||
'bluedroid/BluetoothGattManager.cpp',
|
||||
'bluedroid/BluetoothHALHelpers.cpp',
|
||||
'bluedroid/BluetoothHALInterface.cpp',
|
||||
'bluedroid/BluetoothHandsfreeHALInterface.cpp',
|
||||
|
@ -66,6 +66,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(nsDOMCameraControl, DOMMediaStream,
|
||||
mOnRecorderStateChangeCb,
|
||||
mOnPreviewStateChangeCb,
|
||||
mOnAutoFocusMovingCb,
|
||||
mOnAutoFocusCompletedCb,
|
||||
mOnFacesDetectedCb)
|
||||
|
||||
/* static */
|
||||
@ -155,6 +156,7 @@ nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId,
|
||||
, mOnRecorderStateChangeCb(nullptr)
|
||||
, mOnPreviewStateChangeCb(nullptr)
|
||||
, mOnAutoFocusMovingCb(nullptr)
|
||||
, mOnAutoFocusCompletedCb(nullptr)
|
||||
, mOnFacesDetectedCb(nullptr)
|
||||
, mWindow(aWindow)
|
||||
{
|
||||
@ -618,6 +620,17 @@ nsDOMCameraControl::SetOnAutoFocusMoving(CameraAutoFocusMovingCallback* aCb)
|
||||
mOnAutoFocusMovingCb = aCb;
|
||||
}
|
||||
|
||||
CameraAutoFocusCallback*
|
||||
nsDOMCameraControl::GetOnAutoFocusCompleted()
|
||||
{
|
||||
return mOnAutoFocusCompletedCb;
|
||||
}
|
||||
void
|
||||
nsDOMCameraControl::SetOnAutoFocusCompleted(CameraAutoFocusCallback* aCb)
|
||||
{
|
||||
mOnAutoFocusCompletedCb = aCb;
|
||||
}
|
||||
|
||||
CameraFaceDetectionCallback*
|
||||
nsDOMCameraControl::GetOnFacesDetected()
|
||||
{
|
||||
@ -971,6 +984,7 @@ nsDOMCameraControl::Shutdown()
|
||||
mOnRecorderStateChangeCb = nullptr;
|
||||
mOnPreviewStateChangeCb = nullptr;
|
||||
mOnAutoFocusMovingCb = nullptr;
|
||||
mOnAutoFocusCompletedCb = nullptr;
|
||||
mOnFacesDetectedCb = nullptr;
|
||||
|
||||
mCameraControl->Shutdown();
|
||||
@ -1166,6 +1180,12 @@ nsDOMCameraControl::OnAutoFocusComplete(bool aAutoFocusSucceeded)
|
||||
ErrorResult ignored;
|
||||
cb->Call(aAutoFocusSucceeded, ignored);
|
||||
}
|
||||
|
||||
cb = mOnAutoFocusCompletedCb;
|
||||
if (cb) {
|
||||
ErrorResult ignored;
|
||||
cb->Call(aAutoFocusSucceeded, ignored);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -96,6 +96,8 @@ public:
|
||||
void SetOnPreviewStateChange(dom::CameraPreviewStateChange* aCb);
|
||||
dom::CameraAutoFocusMovingCallback* GetOnAutoFocusMoving();
|
||||
void SetOnAutoFocusMoving(dom::CameraAutoFocusMovingCallback* aCb);
|
||||
dom::CameraAutoFocusCallback* GetOnAutoFocusCompleted();
|
||||
void SetOnAutoFocusCompleted(dom::CameraAutoFocusCallback* aCb);
|
||||
dom::CameraFaceDetectionCallback* GetOnFacesDetected();
|
||||
void SetOnFacesDetected(dom::CameraFaceDetectionCallback* aCb);
|
||||
|
||||
@ -208,6 +210,7 @@ protected:
|
||||
nsRefPtr<dom::CameraRecorderStateChange> mOnRecorderStateChangeCb;
|
||||
nsRefPtr<dom::CameraPreviewStateChange> mOnPreviewStateChangeCb;
|
||||
nsRefPtr<dom::CameraAutoFocusMovingCallback> mOnAutoFocusMovingCb;
|
||||
nsRefPtr<dom::CameraAutoFocusCallback> mOnAutoFocusCompletedCb;
|
||||
nsRefPtr<dom::CameraFaceDetectionCallback> mOnFacesDetectedCb;
|
||||
|
||||
// Camera event listener; we only need this weak reference so that
|
||||
|
@ -35,8 +35,10 @@ var Camera = {
|
||||
|
||||
firstCallFailed: false,
|
||||
secondCallSucceeded: false,
|
||||
callbackTriggered: false,
|
||||
checkForDone: function test_checkForDone() {
|
||||
if (Camera.firstCallFailed && Camera.secondCallSucceeded) {
|
||||
ok(Camera.callbackTriggered, "Async callback triggered");
|
||||
Camera.cameraObj.release();
|
||||
Camera.cameraObj = null;
|
||||
CameraTest.end();
|
||||
@ -60,6 +62,9 @@ var Camera = {
|
||||
failureTwo: function test_failureTwo(error) {
|
||||
ok(false, "Second call to autoFocus() failed unexpectedly with: " + error);
|
||||
},
|
||||
callback: function test_callback(focused) {
|
||||
Camera.callbackTriggered = true;
|
||||
},
|
||||
|
||||
start: function test_start() {
|
||||
function onSuccess(camera, config) {
|
||||
@ -69,6 +74,7 @@ var Camera = {
|
||||
|
||||
// It doesn't matter if the emulator supports focus or not;
|
||||
// this is just testing the sequencing.
|
||||
camera.onAutoFocusCompleted = Camera.callback;
|
||||
camera.autoFocus(Camera.successOne, Camera.failureOne);
|
||||
camera.autoFocus(Camera.successTwo, Camera.failureTwo);
|
||||
};
|
||||
|
@ -153,6 +153,7 @@
|
||||
#include "mozilla/dom/DataStoreService.h"
|
||||
#include "mozilla/dom/telephony/PTelephonyChild.h"
|
||||
#include "mozilla/dom/time/DateCacheCleaner.h"
|
||||
#include "mozilla/dom/voicemail/VoicemailIPCService.h"
|
||||
#include "mozilla/net/NeckoMessageUtils.h"
|
||||
#include "mozilla/RemoteSpellCheckEngineChild.h"
|
||||
|
||||
@ -166,6 +167,7 @@ using namespace mozilla::dom::mobileconnection;
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::hal_sandbox;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
@ -1416,6 +1418,30 @@ ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor)
|
||||
return true;
|
||||
}
|
||||
|
||||
PVoicemailChild*
|
||||
ContentChild::AllocPVoicemailChild()
|
||||
{
|
||||
MOZ_CRASH("No one should be allocating PVoicemailChild actors");
|
||||
}
|
||||
|
||||
PVoicemailChild*
|
||||
ContentChild::SendPVoicemailConstructor(PVoicemailChild* aActor)
|
||||
{
|
||||
aActor = PContentChild::SendPVoicemailConstructor(aActor);
|
||||
if (aActor) {
|
||||
static_cast<VoicemailIPCService*>(aActor)->AddRef();
|
||||
}
|
||||
|
||||
return aActor;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPVoicemailChild(PVoicemailChild* aActor)
|
||||
{
|
||||
static_cast<VoicemailIPCService*>(aActor)->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
PStorageChild*
|
||||
ContentChild::AllocPStorageChild()
|
||||
{
|
||||
|
@ -233,6 +233,10 @@ public:
|
||||
virtual PTelephonyChild* AllocPTelephonyChild() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPTelephonyChild(PTelephonyChild*) MOZ_OVERRIDE;
|
||||
|
||||
virtual PVoicemailChild* AllocPVoicemailChild() MOZ_OVERRIDE;
|
||||
PVoicemailChild* SendPVoicemailConstructor(PVoicemailChild* aActor);
|
||||
virtual bool DeallocPVoicemailChild(PVoicemailChild*) MOZ_OVERRIDE;
|
||||
|
||||
virtual PStorageChild* AllocPStorageChild() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPStorageChild(PStorageChild* aActor) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "mozilla/dom/mobilemessage/SmsParent.h"
|
||||
#include "mozilla/dom/telephony/TelephonyParent.h"
|
||||
#include "mozilla/dom/time/DateCacheCleaner.h"
|
||||
#include "mozilla/dom/voicemail/VoicemailParent.h"
|
||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
@ -196,6 +197,7 @@ using namespace mozilla::dom::power;
|
||||
using namespace mozilla::dom::mobileconnection;
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::hal;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
@ -3160,6 +3162,31 @@ ContentParent::DeallocPTelephonyParent(PTelephonyParent* aActor)
|
||||
return true;
|
||||
}
|
||||
|
||||
PVoicemailParent*
|
||||
ContentParent::AllocPVoicemailParent()
|
||||
{
|
||||
if (!AssertAppProcessPermission(this, "voicemail")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VoicemailParent* actor = new VoicemailParent();
|
||||
actor->AddRef();
|
||||
return actor;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvPVoicemailConstructor(PVoicemailParent* aActor)
|
||||
{
|
||||
return static_cast<VoicemailParent*>(aActor)->Init();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPVoicemailParent(PVoicemailParent* aActor)
|
||||
{
|
||||
static_cast<VoicemailParent*>(aActor)->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
PStorageParent*
|
||||
ContentParent::AllocPStorageParent()
|
||||
{
|
||||
|
@ -487,6 +487,10 @@ private:
|
||||
virtual PTelephonyParent* AllocPTelephonyParent() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPTelephonyParent(PTelephonyParent*) MOZ_OVERRIDE;
|
||||
|
||||
virtual PVoicemailParent* AllocPVoicemailParent() MOZ_OVERRIDE;
|
||||
virtual bool RecvPVoicemailConstructor(PVoicemailParent* aActor) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPVoicemailParent(PVoicemailParent* aActor) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool DeallocPStorageParent(PStorageParent* aActor) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBluetoothParent* AllocPBluetoothParent() MOZ_OVERRIDE;
|
||||
|
@ -31,6 +31,7 @@ include protocol PSpeechSynthesis;
|
||||
include protocol PStorage;
|
||||
include protocol PTelephony;
|
||||
include protocol PTestShell;
|
||||
include protocol PVoicemail;
|
||||
include protocol PJavaScript;
|
||||
include protocol PRemoteSpellcheckEngine;
|
||||
include DOMTypes;
|
||||
@ -338,6 +339,7 @@ intr protocol PContent
|
||||
manages PStorage;
|
||||
manages PTelephony;
|
||||
manages PTestShell;
|
||||
manages PVoicemail;
|
||||
manages PJavaScript;
|
||||
manages PRemoteSpellcheckEngine;
|
||||
|
||||
@ -539,6 +541,8 @@ parent:
|
||||
|
||||
PTelephony();
|
||||
|
||||
PVoicemail();
|
||||
|
||||
PBluetooth();
|
||||
|
||||
PFMRadio();
|
||||
|
@ -90,6 +90,7 @@ DIRS += [
|
||||
'promise',
|
||||
'smil',
|
||||
'telephony',
|
||||
'voicemail',
|
||||
'inputmethod',
|
||||
'webidl',
|
||||
'xbl',
|
||||
@ -112,7 +113,6 @@ if CONFIG['MOZ_B2G_RIL']:
|
||||
DIRS += [
|
||||
'icc',
|
||||
'cellbroadcast',
|
||||
'voicemail',
|
||||
'wappush',
|
||||
]
|
||||
|
||||
|
@ -33,7 +33,6 @@ const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
|
||||
const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
|
||||
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
|
||||
const kPrefVoicemailDefaultServiceId = "dom.voicemail.defaultServiceId";
|
||||
|
||||
let DEBUG;
|
||||
function debug(s) {
|
||||
@ -48,8 +47,6 @@ const GSMICCINFO_CID =
|
||||
Components.ID("{e0fa785b-ad3f-46ed-bc56-fcb0d6fe4fa8}");
|
||||
const CDMAICCINFO_CID =
|
||||
Components.ID("{3d1f844f-9ec5-48fb-8907-aed2e5421709}");
|
||||
const VOICEMAILSTATUS_CID=
|
||||
Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
|
||||
const CELLBROADCASTMESSAGE_CID =
|
||||
Components.ID("{29474c96-3099-486f-bb4a-3c9a1da834e4}");
|
||||
const CELLBROADCASTETWSINFO_CID =
|
||||
@ -60,8 +57,6 @@ const ICCCARDLOCKERROR_CID =
|
||||
const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:CardStateChanged",
|
||||
"RIL:IccInfoChanged",
|
||||
"RIL:VoicemailNotification",
|
||||
"RIL:VoicemailInfoChanged",
|
||||
"RIL:CardLockResult",
|
||||
"RIL:CardLockRetryCount",
|
||||
"RIL:StkCommand",
|
||||
@ -173,27 +168,6 @@ CdmaIccInfo.prototype = {
|
||||
prlVersion: 0
|
||||
};
|
||||
|
||||
function VoicemailInfo() {}
|
||||
VoicemailInfo.prototype = {
|
||||
number: null,
|
||||
displayName: null
|
||||
};
|
||||
|
||||
function VoicemailStatus(clientId) {
|
||||
this.serviceId = clientId;
|
||||
}
|
||||
VoicemailStatus.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([]),
|
||||
classID: VOICEMAILSTATUS_CID,
|
||||
contractID: "@mozilla.org/voicemailstatus;1",
|
||||
|
||||
serviceId: -1,
|
||||
hasMessages: false,
|
||||
messageCount: -1, // Count unknown.
|
||||
returnNumber: null,
|
||||
returnMessage: null
|
||||
};
|
||||
|
||||
function CellBroadcastMessage(clientId, pdu) {
|
||||
this.serviceId = clientId;
|
||||
this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
|
||||
@ -280,36 +254,27 @@ function RILContentHelper() {
|
||||
if (DEBUG) debug("Number of clients: " + this.numClients);
|
||||
|
||||
this.rilContexts = [];
|
||||
this.voicemailInfos = [];
|
||||
this.voicemailStatuses = [];
|
||||
for (let clientId = 0; clientId < this.numClients; clientId++) {
|
||||
this.rilContexts[clientId] = {
|
||||
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
|
||||
iccInfo: null
|
||||
};
|
||||
|
||||
this.voicemailInfos[clientId] = new VoicemailInfo();
|
||||
}
|
||||
|
||||
this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
|
||||
|
||||
this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
|
||||
this._windowsMap = [];
|
||||
this._cellBroadcastListeners = [];
|
||||
this._voicemailListeners = [];
|
||||
this._iccListeners = [];
|
||||
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
|
||||
Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
|
||||
Services.prefs.addObserver(kPrefVoicemailDefaultServiceId, this, false);
|
||||
}
|
||||
|
||||
RILContentHelper.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellBroadcastProvider,
|
||||
Ci.nsIVoicemailProvider,
|
||||
Ci.nsIIccProvider,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
@ -317,7 +282,6 @@ RILContentHelper.prototype = {
|
||||
classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
|
||||
classDescription: "RILContentHelper",
|
||||
interfaces: [Ci.nsICellBroadcastProvider,
|
||||
Ci.nsIVoicemailProvider,
|
||||
Ci.nsIIccProvider]}),
|
||||
|
||||
updateDebugFlag: function() {
|
||||
@ -675,52 +639,8 @@ RILContentHelper.prototype = {
|
||||
},
|
||||
|
||||
_cellBroadcastListeners: null,
|
||||
_voicemailListeners: null,
|
||||
_iccListeners: null,
|
||||
|
||||
voicemailInfos: null,
|
||||
voicemailStatuses: null,
|
||||
|
||||
voicemailDefaultServiceId: 0,
|
||||
getVoicemailDefaultServiceId: function() {
|
||||
let id = Services.prefs.getIntPref(kPrefVoicemailDefaultServiceId);
|
||||
|
||||
if (id >= gNumRadioInterfaces || id < 0) {
|
||||
id = 0;
|
||||
}
|
||||
|
||||
return id;
|
||||
},
|
||||
|
||||
getVoicemailInfo: function(clientId) {
|
||||
// Get voicemail infomation by IPC only on first time.
|
||||
this.getVoicemailInfo = function getVoicemailInfo(clientId) {
|
||||
return this.voicemailInfos[clientId];
|
||||
};
|
||||
|
||||
for (let cId = 0; cId < gNumRadioInterfaces; cId++) {
|
||||
let voicemailInfo =
|
||||
cpmm.sendSyncMessage("RIL:GetVoicemailInfo", {clientId: cId})[0];
|
||||
if (voicemailInfo) {
|
||||
this.updateInfo(voicemailInfo, this.voicemailInfos[cId]);
|
||||
}
|
||||
}
|
||||
|
||||
return this.voicemailInfos[clientId];
|
||||
},
|
||||
|
||||
getVoicemailNumber: function(clientId) {
|
||||
return this.getVoicemailInfo(clientId).number;
|
||||
},
|
||||
|
||||
getVoicemailDisplayName: function(clientId) {
|
||||
return this.getVoicemailInfo(clientId).displayName;
|
||||
},
|
||||
|
||||
getVoicemailStatus: function(clientId) {
|
||||
return this.voicemailStatuses[clientId];
|
||||
},
|
||||
|
||||
registerListener: function(listenerType, clientId, listener) {
|
||||
if (!this[listenerType]) {
|
||||
return;
|
||||
@ -754,22 +674,6 @@ RILContentHelper.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
registerVoicemailMsg: function(listener) {
|
||||
if (DEBUG) debug("Registering for voicemail-related messages");
|
||||
// To follow the listener registration scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
// See |handleVoicemailNotification|.
|
||||
this.registerListener("_voicemailListeners", 0, listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
|
||||
},
|
||||
|
||||
unregisterVoicemailMsg: function(listener) {
|
||||
// To follow the listener unregistration scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
// See |handleVoicemailNotification|.
|
||||
this.unregisterListener("_voicemailListeners", 0, listener);
|
||||
},
|
||||
|
||||
registerCellBroadcastMsg: function(listener) {
|
||||
if (DEBUG) debug("Registering for Cell Broadcast related messages");
|
||||
// Instead of registering multiple listeners for Multi-SIM, we reuse
|
||||
@ -803,8 +707,6 @@ RILContentHelper.prototype = {
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
|
||||
if (data == kPrefRilDebuggingEnabled) {
|
||||
this.updateDebugFlag();
|
||||
} else if (data == kPrefVoicemailDefaultServiceId) {
|
||||
this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -903,12 +805,6 @@ RILContentHelper.prototype = {
|
||||
"notifyIccInfoChanged",
|
||||
null);
|
||||
break;
|
||||
case "RIL:VoicemailNotification":
|
||||
this.handleVoicemailNotification(clientId, data);
|
||||
break;
|
||||
case "RIL:VoicemailInfoChanged":
|
||||
this.updateInfo(data, this.voicemailInfos[clientId]);
|
||||
break;
|
||||
case "RIL:CardLockResult": {
|
||||
let requestId = data.requestId;
|
||||
let requestWindow = this._windowsMap[requestId];
|
||||
@ -1050,46 +946,6 @@ RILContentHelper.prototype = {
|
||||
this.fireRequestSuccess(message.requestId, contact);
|
||||
},
|
||||
|
||||
handleVoicemailNotification: function(clientId, message) {
|
||||
let changed = false;
|
||||
if (!this.voicemailStatuses[clientId]) {
|
||||
this.voicemailStatuses[clientId] = new VoicemailStatus(clientId);
|
||||
}
|
||||
|
||||
let voicemailStatus = this.voicemailStatuses[clientId];
|
||||
if (voicemailStatus.hasMessages != message.active) {
|
||||
changed = true;
|
||||
voicemailStatus.hasMessages = message.active;
|
||||
}
|
||||
|
||||
if (voicemailStatus.messageCount != message.msgCount) {
|
||||
changed = true;
|
||||
voicemailStatus.messageCount = message.msgCount;
|
||||
} else if (message.msgCount == -1) {
|
||||
// For MWI using DCS the message count is not available
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (voicemailStatus.returnNumber != message.returnNumber) {
|
||||
changed = true;
|
||||
voicemailStatus.returnNumber = message.returnNumber;
|
||||
}
|
||||
|
||||
if (voicemailStatus.returnMessage != message.returnMessage) {
|
||||
changed = true;
|
||||
voicemailStatus.returnMessage = message.returnMessage;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
// To follow the event delivering scheme, we add a dummy clientId 0.
|
||||
// All voicemail events are routed to listener for client id 0.
|
||||
this._deliverEvent(0,
|
||||
"_voicemailListeners",
|
||||
"notifyStatusChanged",
|
||||
[voicemailStatus]);
|
||||
}
|
||||
},
|
||||
|
||||
_deliverEvent: function(clientId, listenerType, name, args) {
|
||||
if (!this[listenerType]) {
|
||||
return;
|
||||
|
@ -127,11 +127,6 @@ const RIL_IPC_ICCMANAGER_MSG_NAMES = [
|
||||
"RIL:MatchMvno"
|
||||
];
|
||||
|
||||
const RIL_IPC_VOICEMAIL_MSG_NAMES = [
|
||||
"RIL:RegisterVoicemailMsg",
|
||||
"RIL:GetVoicemailInfo"
|
||||
];
|
||||
|
||||
const RIL_IPC_CELLBROADCAST_MSG_NAMES = [
|
||||
"RIL:RegisterCellBroadcastMsg"
|
||||
];
|
||||
@ -250,9 +245,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
for (let msgName of RIL_IPC_ICCMANAGER_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_VOICEMAIL_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_CELLBROADCAST_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
@ -263,9 +255,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
for (let msgName of RIL_IPC_ICCMANAGER_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgName, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_VOICEMAIL_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_CELLBROADCAST_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
@ -384,14 +373,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else if (RIL_IPC_VOICEMAIL_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (!msg.target.assertPermission("voicemail")) {
|
||||
if (DEBUG) {
|
||||
debug("Voicemail message " + msg.name +
|
||||
" from a content process with no 'voicemail' privileges.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else if (RIL_IPC_CELLBROADCAST_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (!msg.target.assertPermission("cellbroadcast")) {
|
||||
if (DEBUG) {
|
||||
@ -409,9 +390,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
case "RIL:RegisterIccMsg":
|
||||
this._registerMessageTarget("icc", msg.target);
|
||||
return null;
|
||||
case "RIL:RegisterVoicemailMsg":
|
||||
this._registerMessageTarget("voicemail", msg.target);
|
||||
return null;
|
||||
case "RIL:RegisterCellBroadcastMsg":
|
||||
this._registerMessageTarget("cellbroadcast", msg.target);
|
||||
return null;
|
||||
@ -450,13 +428,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
});
|
||||
},
|
||||
|
||||
sendVoicemailMessage: function(message, clientId, data) {
|
||||
this._sendTargetMessage("voicemail", message, {
|
||||
clientId: clientId,
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
sendCellBroadcastMessage: function(message, clientId, data) {
|
||||
this._sendTargetMessage("cellbroadcast", message, {
|
||||
clientId: clientId,
|
||||
@ -1883,11 +1854,6 @@ function RadioInterface(aClientId, aWorkerMessenger) {
|
||||
imsi: null
|
||||
};
|
||||
|
||||
this.voicemailInfo = {
|
||||
number: null,
|
||||
displayName: null
|
||||
};
|
||||
|
||||
this.operatorInfo = {};
|
||||
|
||||
let lock = gSettingsService.createLock();
|
||||
@ -2067,9 +2033,6 @@ RadioInterface.prototype = {
|
||||
case "RIL:MatchMvno":
|
||||
this.matchMvno(msg.target, msg.json.data);
|
||||
break;
|
||||
case "RIL:GetVoicemailInfo":
|
||||
// This message is sync.
|
||||
return this.voicemailInfo;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@ -2183,8 +2146,7 @@ RadioInterface.prototype = {
|
||||
this.handleIccMbdn(message);
|
||||
break;
|
||||
case "iccmwis":
|
||||
gMessageManager.sendVoicemailMessage("RIL:VoicemailNotification",
|
||||
this.clientId, message.mwi);
|
||||
this.handleIccMwis(message.mwi);
|
||||
break;
|
||||
case "stkcommand":
|
||||
this.handleStkProactiveCommand(message);
|
||||
@ -2763,8 +2725,7 @@ RadioInterface.prototype = {
|
||||
|
||||
mwi.returnNumber = message.sender;
|
||||
mwi.returnMessage = message.fullBody;
|
||||
gMessageManager.sendVoicemailMessage("RIL:VoicemailNotification",
|
||||
this.clientId, mwi);
|
||||
this.handleIccMwis(mwi);
|
||||
|
||||
// Dicarded MWI comes without text body.
|
||||
// Hence, we discard it here after notifying the MWI status.
|
||||
@ -2968,13 +2929,16 @@ RadioInterface.prototype = {
|
||||
},
|
||||
|
||||
handleIccMbdn: function(message) {
|
||||
let voicemailInfo = this.voicemailInfo;
|
||||
let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
|
||||
.getService(Ci.nsIGonkVoicemailService);
|
||||
service.notifyInfoChanged(this.clientId, message.number, message.alphaId);
|
||||
},
|
||||
|
||||
voicemailInfo.number = message.number;
|
||||
voicemailInfo.displayName = message.alphaId;
|
||||
|
||||
gMessageManager.sendVoicemailMessage("RIL:VoicemailInfoChanged",
|
||||
this.clientId, voicemailInfo);
|
||||
handleIccMwis: function(mwi) {
|
||||
let service = Cc["@mozilla.org/voicemail/voicemailservice;1"]
|
||||
.getService(Ci.nsIGonkVoicemailService);
|
||||
service.notifyStatusChanged(this.clientId, mwi.active, mwi.msgCount,
|
||||
mwi.returnNumber, mwi.returnMessage);
|
||||
},
|
||||
|
||||
handleIccInfoChange: function(message) {
|
||||
|
@ -18,10 +18,8 @@ contract @mozilla.org/ril;1 {2d831c8d-6017-435b-a80c-e5d422810cea}
|
||||
category profile-after-change RadioInterfaceLayer @mozilla.org/ril;1
|
||||
|
||||
# RILContentHelper.js
|
||||
component {5467f2eb-e214-43ea-9b89-67711241ec8e} RILContentHelper.js
|
||||
component {472816e1-1fd6-4405-996c-806f9ea68174} RILContentHelper.js
|
||||
component {08a71987-408c-44ff-93fd-177c0a85c3dd} RILContentHelper.js
|
||||
contract @mozilla.org/voicemailstatus;1 {5467f2eb-e214-43ea-9b89-67711241ec8e}
|
||||
contract @mozilla.org/ril/content-helper;1 {472816e1-1fd6-4405-996c-806f9ea68174}
|
||||
contract @mozilla.org/dom/icccardlock-error;1 {08a71987-408c-44ff-93fd-177c0a85c3dd}
|
||||
category profile-after-change RILContentHelper @mozilla.org/ril/content-helper;1
|
||||
|
@ -23,14 +23,6 @@ interface nsIRilNetworkInterface : nsINetworkInterface
|
||||
readonly attribute long mmsPort; // -1 if not set.
|
||||
};
|
||||
|
||||
[scriptable, uuid(c0c5cb9f-6372-4b5a-b74c-baacc2da5e4f)]
|
||||
interface nsIVoicemailInfo : nsISupports
|
||||
{
|
||||
readonly attribute DOMString number;
|
||||
|
||||
readonly attribute DOMString displayName;
|
||||
};
|
||||
|
||||
[scriptable, uuid(0226a2c1-a3b9-416a-92cb-c89e4dad4be0)]
|
||||
interface nsIRilContext : nsISupports
|
||||
{
|
||||
|
@ -10524,6 +10524,32 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
return method.call(this, cmdDetails, ctlvs);
|
||||
},
|
||||
|
||||
loadIconIfNecessary: function(cmdDetails, ctlvs, ret) {
|
||||
let ctlv =
|
||||
this.context.StkProactiveCmdHelper
|
||||
.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
ret.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
ret.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
ret.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
* Construct a param for Refresh.
|
||||
*
|
||||
@ -10733,27 +10759,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
textMsg.userClear = true;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return textMsg;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
textMsg.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
textMsg.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return textMsg;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, textMsg);
|
||||
},
|
||||
|
||||
processSetUpIdleModeText: function(cmdDetails, ctlvs) {
|
||||
@ -10770,27 +10776,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
}
|
||||
textMsg.text = ctlv.value.textString;
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return textMsg;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
textMsg.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
textMsg.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return textMsg;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, textMsg);
|
||||
},
|
||||
|
||||
processGetInkey: function(cmdDetails, ctlvs) {
|
||||
@ -10837,27 +10823,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
input.isHelpAvailable = true;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return input;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
input.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
input.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
input.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return input;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, input);
|
||||
},
|
||||
|
||||
processGetInput: function(cmdDetails, ctlvs) {
|
||||
@ -10909,27 +10875,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
input.isHelpAvailable = true;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return input;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
input.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
input.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
input.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return input;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, input);
|
||||
},
|
||||
|
||||
processEventNotify: function(cmdDetails, ctlvs) {
|
||||
@ -10942,28 +10888,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
textMsg.text = ctlv.value.identifier;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(
|
||||
COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return textMsg;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
textMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
textMsg.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
textMsg.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return textMsg;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, textMsg);
|
||||
},
|
||||
|
||||
processSetupCall: function(cmdDetails, ctlvs) {
|
||||
@ -10996,27 +10921,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
call.duration = ctlv.value;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return call;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
call.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
call.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
call.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return call;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, call);
|
||||
},
|
||||
|
||||
processLaunchBrowser: function(cmdDetails, ctlvs) {
|
||||
@ -11039,27 +10944,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
|
||||
browser.mode = cmdDetails.commandQualifier & 0x03;
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return browser;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
browser.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
browser.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
browser.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return browser;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, browser);
|
||||
},
|
||||
|
||||
processPlayTone: function(cmdDetails, ctlvs) {
|
||||
@ -11086,28 +10971,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
// vibrate is only defined in TS 102.223
|
||||
playTone.isVibrate = (cmdDetails.commandQualifier & 0x01) !== 0x00;
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(
|
||||
COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return playTone;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
playTone.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
playTone.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
playTone.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return playTone;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, playTone);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -11164,27 +11028,7 @@ StkCommandParamsFactoryObject.prototype = {
|
||||
bipMsg.text = ctlv.value.identifier;
|
||||
}
|
||||
|
||||
ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ICON_ID, ctlvs);
|
||||
if (!ctlv || !this.context.ICCUtilsHelper.isICCServiceAvailable("IMG")) {
|
||||
return bipMsg;
|
||||
}
|
||||
|
||||
let iconId = ctlv.value;
|
||||
bipMsg.iconSelfExplanatory = iconId.qualifier == 0 ? true : false;
|
||||
|
||||
let onerror = (function() {
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
let onsuccess = (function(result) {
|
||||
bipMsg.icons = result[0];
|
||||
this.context.RIL.sendChromeMessage(cmdDetails);
|
||||
}).bind(this);
|
||||
|
||||
bipMsg.pending = true;
|
||||
this.context.IconLoader.loadIcons([iconId.identifier], onsuccess, onerror);
|
||||
|
||||
return bipMsg;
|
||||
return this.loadIconIfNecessary(cmdDetails, ctlvs, bipMsg);
|
||||
}
|
||||
};
|
||||
StkCommandParamsFactoryObject.prototype[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Voicemail.h"
|
||||
#include "mozilla/dom/Voicemail.h"
|
||||
|
||||
#include "mozilla/dom/MozVoicemailBinding.h"
|
||||
#include "mozilla/dom/MozVoicemailEvent.h"
|
||||
@ -13,13 +13,17 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"
|
||||
const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
|
||||
// Service instantiation
|
||||
#include "ipc/VoicemailIPCService.h"
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
#include "nsIGonkVoicemailService.h"
|
||||
#endif
|
||||
#include "nsXULAppAPI.h" // For XRE_GetProcessType()
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::ErrorResult;
|
||||
|
||||
class Voicemail::Listener MOZ_FINAL : public nsIVoicemailListener
|
||||
{
|
||||
@ -50,26 +54,67 @@ private:
|
||||
|
||||
NS_IMPL_ISUPPORTS(Voicemail::Listener, nsIVoicemailListener)
|
||||
|
||||
Voicemail::Voicemail(nsPIDOMWindow* aWindow,
|
||||
nsIVoicemailProvider* aProvider)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mProvider(aProvider)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(Voicemail, DOMEventTargetHelper,
|
||||
mStatuses)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Voicemail)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Voicemail, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Voicemail, DOMEventTargetHelper)
|
||||
|
||||
/* static */ already_AddRefed<Voicemail>
|
||||
Voicemail::Create(nsPIDOMWindow* aWindow,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIVoicemailService> service =
|
||||
do_GetService(NS_VOICEMAIL_SERVICE_CONTRACTID);
|
||||
if (!service) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
|
||||
aWindow :
|
||||
aWindow->GetCurrentInnerWindow();
|
||||
|
||||
nsRefPtr<Voicemail> voicemail = new Voicemail(innerWindow, service);
|
||||
return voicemail.forget();
|
||||
}
|
||||
|
||||
Voicemail::Voicemail(nsPIDOMWindow* aWindow,
|
||||
nsIVoicemailService* aService)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mService(aService)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
|
||||
mListener = new Listener(this);
|
||||
DebugOnly<nsresult> rv = mProvider->RegisterVoicemailMsg(mListener);
|
||||
DebugOnly<nsresult> rv = mService->RegisterListener(mListener);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"Failed registering voicemail messages with provider");
|
||||
"Failed registering voicemail messages with service");
|
||||
|
||||
uint32_t length = 0;
|
||||
if (NS_SUCCEEDED(mService->GetNumItems(&length)) && length != 0) {
|
||||
mStatuses.SetLength(length);
|
||||
}
|
||||
}
|
||||
|
||||
Voicemail::~Voicemail()
|
||||
{
|
||||
MOZ_ASSERT(mProvider && mListener);
|
||||
|
||||
mListener->Disconnect();
|
||||
mProvider->UnregisterVoicemailMsg(mListener);
|
||||
MOZ_ASSERT(!mService && !mListener);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(Voicemail, DOMEventTargetHelper)
|
||||
void
|
||||
Voicemail::Shutdown()
|
||||
{
|
||||
mListener->Disconnect();
|
||||
mService->UnregisterListener(mListener);
|
||||
|
||||
mListener = nullptr;
|
||||
mService = nullptr;
|
||||
mStatuses.Clear();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Voicemail::WrapObject(JSContext* aCx)
|
||||
@ -77,133 +122,143 @@ Voicemail::WrapObject(JSContext* aCx)
|
||||
return MozVoicemailBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
bool
|
||||
Voicemail::IsValidServiceId(uint32_t aServiceId) const
|
||||
already_AddRefed<nsIVoicemailProvider>
|
||||
Voicemail::GetItemByServiceId(const Optional<uint32_t>& aOptionalServiceId,
|
||||
uint32_t& aActualServiceId) const
|
||||
{
|
||||
uint32_t numClients = mozilla::Preferences::GetUint(kPrefRilNumRadioInterfaces, 1);
|
||||
|
||||
return aServiceId < numClients;
|
||||
}
|
||||
|
||||
bool
|
||||
Voicemail::PassedOrDefaultServiceId(const Optional<uint32_t>& aServiceId,
|
||||
uint32_t& aResult) const
|
||||
{
|
||||
if (aServiceId.WasPassed()) {
|
||||
if (!IsValidServiceId(aServiceId.Value())) {
|
||||
return false;
|
||||
}
|
||||
aResult = aServiceId.Value();
|
||||
} else {
|
||||
mProvider->GetVoicemailDefaultServiceId(&aResult);
|
||||
if (!mService) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
nsCOMPtr<nsIVoicemailProvider> provider;
|
||||
if (aOptionalServiceId.WasPassed()) {
|
||||
aActualServiceId = aOptionalServiceId.Value();
|
||||
mService->GetItemByServiceId(aActualServiceId,
|
||||
getter_AddRefs(provider));
|
||||
} else {
|
||||
mService->GetDefaultItem(getter_AddRefs(provider));
|
||||
if (provider) {
|
||||
NS_ENSURE_SUCCESS(provider->GetServiceId(&aActualServiceId), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// For all retrieved providers, they should have service id
|
||||
// < mStatuses.Length().
|
||||
MOZ_ASSERT(!provider || aActualServiceId < mStatuses.Length());
|
||||
return provider.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<VoicemailStatus>
|
||||
Voicemail::GetOrCreateStatus(uint32_t aServiceId,
|
||||
nsIVoicemailProvider* aProvider)
|
||||
{
|
||||
MOZ_ASSERT(aServiceId < mStatuses.Length());
|
||||
MOZ_ASSERT(aProvider);
|
||||
|
||||
nsRefPtr<VoicemailStatus> res = mStatuses[aServiceId];
|
||||
if (!res) {
|
||||
mStatuses[aServiceId] = res = new VoicemailStatus(GetOwner(), aProvider);
|
||||
}
|
||||
|
||||
return res.forget();
|
||||
}
|
||||
|
||||
// MozVoicemail WebIDL
|
||||
|
||||
already_AddRefed<MozVoicemailStatus>
|
||||
already_AddRefed<VoicemailStatus>
|
||||
Voicemail::GetStatus(const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv) const
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!mProvider) {
|
||||
uint32_t actualServiceId = 0;
|
||||
nsCOMPtr<nsIVoicemailProvider> provider =
|
||||
GetItemByServiceId(aServiceId, actualServiceId);
|
||||
if (!provider) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return nullptr;
|
||||
}
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
JS::Rooted<JS::Value> status(cx);
|
||||
nsresult rv = mProvider->GetVoicemailStatus(id, &status);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
if (!status.isObject()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
JS::Rooted<JSObject*> statusObj(cx, &status.toObject());
|
||||
nsRefPtr<MozVoicemailStatus> res = new MozVoicemailStatus(statusObj, GetParentObject());
|
||||
return res.forget();
|
||||
return GetOrCreateStatus(actualServiceId, provider);
|
||||
}
|
||||
|
||||
void
|
||||
Voicemail::GetNumber(const Optional<uint32_t>& aServiceId, nsString& aNumber,
|
||||
Voicemail::GetNumber(const Optional<uint32_t>& aServiceId,
|
||||
nsString& aNumber,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
aNumber.SetIsVoid(true);
|
||||
|
||||
if (!mProvider) {
|
||||
uint32_t unused = 0;
|
||||
nsCOMPtr<nsIVoicemailProvider> provider =
|
||||
GetItemByServiceId(aServiceId, unused);
|
||||
if (!provider) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailNumber(id, aNumber);
|
||||
aRv = provider->GetNumber(aNumber);
|
||||
}
|
||||
|
||||
void
|
||||
Voicemail::GetDisplayName(const Optional<uint32_t>& aServiceId, nsString& aDisplayName,
|
||||
Voicemail::GetDisplayName(const Optional<uint32_t>& aServiceId,
|
||||
nsString& aDisplayName,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
aDisplayName.SetIsVoid(true);
|
||||
|
||||
if (!mProvider) {
|
||||
uint32_t unused = 0;
|
||||
nsCOMPtr<nsIVoicemailProvider> provider =
|
||||
GetItemByServiceId(aServiceId, unused);
|
||||
if (!provider) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
if (!PassedOrDefaultServiceId(aServiceId, id)) {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mProvider->GetVoicemailDisplayName(id, aDisplayName);
|
||||
aRv = provider->GetDisplayName(aDisplayName);
|
||||
}
|
||||
|
||||
// nsIVoicemailListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
Voicemail::NotifyStatusChanged(JS::HandleValue aStatus)
|
||||
Voicemail::NotifyInfoChanged(nsIVoicemailProvider* aProvider)
|
||||
{
|
||||
// Ignored.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Voicemail::NotifyStatusChanged(nsIVoicemailProvider* aProvider)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProvider);
|
||||
|
||||
uint32_t serviceId = 0;
|
||||
if (NS_FAILED(aProvider->GetServiceId(&serviceId))) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
MozVoicemailEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
if (aStatus.isObject()) {
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
JS::Rooted<JSObject*> statusObj(cx, &aStatus.toObject());
|
||||
init.mStatus = new MozVoicemailStatus(statusObj, GetParentObject());
|
||||
}
|
||||
init.mStatus = GetOrCreateStatus(serviceId, aProvider);
|
||||
|
||||
nsRefPtr<MozVoicemailEvent> event =
|
||||
MozVoicemailEvent::Constructor(this, NS_LITERAL_STRING("statuschanged"), init);
|
||||
return DispatchTrustedEvent(event);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewVoicemail(nsPIDOMWindow* aWindow, Voicemail** aVoicemail)
|
||||
already_AddRefed<nsIVoicemailService>
|
||||
NS_CreateVoicemailService()
|
||||
{
|
||||
nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
|
||||
aWindow :
|
||||
aWindow->GetCurrentInnerWindow();
|
||||
nsCOMPtr<nsIVoicemailService> service;
|
||||
|
||||
nsCOMPtr<nsIVoicemailProvider> provider =
|
||||
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
NS_ENSURE_STATE(provider);
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
service = new mozilla::dom::voicemail::VoicemailIPCService();
|
||||
} else {
|
||||
#if defined(MOZ_B2G_RIL)
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
service = do_GetService(GONK_VOICEMAIL_SERVICE_CONTRACTID);
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
#endif // MOZ_B2G_RIL
|
||||
}
|
||||
|
||||
nsRefPtr<Voicemail> voicemail = new Voicemail(innerWindow, provider);
|
||||
voicemail.forget(aVoicemail);
|
||||
return NS_OK;
|
||||
return service.forget();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@ -10,7 +10,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsIVoicemailProvider.h"
|
||||
#include "nsIVoicemailService.h"
|
||||
|
||||
class JSObject;
|
||||
struct JSContext;
|
||||
@ -20,7 +20,7 @@ class nsPIDOMWindow;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MozVoicemailStatus;
|
||||
class VoicemailStatus;
|
||||
|
||||
class Voicemail MOZ_FINAL : public DOMEventTargetHelper,
|
||||
private nsIVoicemailListener
|
||||
@ -28,21 +28,25 @@ class Voicemail MOZ_FINAL : public DOMEventTargetHelper,
|
||||
/**
|
||||
* Class Voicemail doesn't actually expose nsIVoicemailListener. Instead, it
|
||||
* owns an nsIVoicemailListener derived instance mListener and passes it to
|
||||
* nsIVoicemailProvider. The onreceived events are first delivered to
|
||||
* nsIVoicemailService. The onreceived events are first delivered to
|
||||
* mListener and then forwarded to its owner, Voicemail. See also bug 775997
|
||||
* comment #51.
|
||||
*/
|
||||
class Listener;
|
||||
|
||||
virtual ~Voicemail();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIVOICEMAILLISTENER
|
||||
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Voicemail,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
Voicemail(nsPIDOMWindow* aWindow, nsIVoicemailProvider* aProvider);
|
||||
static already_AddRefed<Voicemail>
|
||||
Create(nsPIDOMWindow* aOwner,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Shutdown();
|
||||
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
@ -53,36 +57,54 @@ public:
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<MozVoicemailStatus>
|
||||
GetStatus(const Optional<uint32_t>& aServiceId, ErrorResult& aRv) const;
|
||||
already_AddRefed<VoicemailStatus>
|
||||
GetStatus(const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetNumber(const Optional<uint32_t>& aServiceId, nsString& aNumber,
|
||||
GetNumber(const Optional<uint32_t>& aServiceId,
|
||||
nsString& aNumber,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
void
|
||||
GetDisplayName(const Optional<uint32_t>& aServiceId, nsString& aDisplayName,
|
||||
GetDisplayName(const Optional<uint32_t>& aServiceId,
|
||||
nsString& aDisplayName,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(statuschanged)
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIVoicemailProvider> mProvider;
|
||||
Voicemail(nsPIDOMWindow* aWindow,
|
||||
nsIVoicemailService* aService);
|
||||
|
||||
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
|
||||
~Voicemail();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIVoicemailService> mService;
|
||||
nsRefPtr<Listener> mListener;
|
||||
|
||||
bool
|
||||
IsValidServiceId(uint32_t aServiceId) const;
|
||||
// |mStatuses| keeps all instantiated VoicemailStatus objects as well as the
|
||||
// empty slots for not interested ones. The length of |mStatuses| is decided
|
||||
// in the constructor and is never changed ever since.
|
||||
nsAutoTArray<nsRefPtr<VoicemailStatus>, 1> mStatuses;
|
||||
|
||||
bool
|
||||
PassedOrDefaultServiceId(const Optional<uint32_t>& aServiceId,
|
||||
uint32_t& aResult) const;
|
||||
// Return a nsIVoicemailProvider instance based on the requests from external
|
||||
// components. Return nullptr if aOptionalServiceId contains an invalid
|
||||
// service id or the default one is just not available.
|
||||
already_AddRefed<nsIVoicemailProvider>
|
||||
GetItemByServiceId(const Optional<uint32_t>& aOptionalServiceId,
|
||||
uint32_t& aActualServiceId) const;
|
||||
|
||||
// Request for a valid VoicemailStatus object based on given service id and
|
||||
// provider. It's the callee's responsibility to ensure the validity of the
|
||||
// two parameters.
|
||||
already_AddRefed<VoicemailStatus>
|
||||
GetOrCreateStatus(uint32_t aServiceId,
|
||||
nsIVoicemailProvider* aProvider);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
nsresult
|
||||
NS_NewVoicemail(nsPIDOMWindow* aWindow,
|
||||
mozilla::dom::Voicemail** aVoicemail);
|
||||
|
||||
#endif // mozilla_dom_voicemail_voicemail_h__
|
||||
|
83
dom/voicemail/VoicemailStatus.cpp
Normal file
83
dom/voicemail/VoicemailStatus.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/VoicemailStatus.h"
|
||||
|
||||
#include "mozilla/dom/MozVoicemailStatusBinding.h"
|
||||
#include "nsIVoicemailService.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// mProvider is owned by internal service.
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VoicemailStatus, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(VoicemailStatus)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(VoicemailStatus)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VoicemailStatus)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
VoicemailStatus::VoicemailStatus(nsISupports* aParent,
|
||||
nsIVoicemailProvider* aProvider)
|
||||
: mParent(aParent)
|
||||
, mProvider(aProvider)
|
||||
{
|
||||
MOZ_ASSERT(mParent);
|
||||
MOZ_ASSERT(mProvider);
|
||||
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
VoicemailStatus::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MozVoicemailStatusBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VoicemailStatus::ServiceId() const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
mProvider->GetServiceId(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
VoicemailStatus::HasMessages() const
|
||||
{
|
||||
bool result = false;
|
||||
mProvider->GetHasMessages(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
VoicemailStatus::MessageCount() const
|
||||
{
|
||||
int32_t result = 0;
|
||||
mProvider->GetMessageCount(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
VoicemailStatus::GetReturnNumber(nsString& aReturnNumber) const
|
||||
{
|
||||
aReturnNumber.SetIsVoid(true);
|
||||
mProvider->GetReturnNumber(aReturnNumber);
|
||||
}
|
||||
|
||||
void
|
||||
VoicemailStatus::GetReturnMessage(nsString& aReturnMessage) const
|
||||
{
|
||||
aReturnMessage.SetIsVoid(true);
|
||||
mProvider->GetReturnMessage(aReturnMessage);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
64
dom/voicemail/VoicemailStatus.h
Normal file
64
dom/voicemail/VoicemailStatus.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_voicemail_VoicemailStatus_h__
|
||||
#define mozilla_dom_voicemail_VoicemailStatus_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIVoicemailService.h" // For nsIVoicemailProvider.
|
||||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class VoicemailStatus MOZ_FINAL : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(VoicemailStatus)
|
||||
|
||||
VoicemailStatus(nsISupports* aParent,
|
||||
nsIVoicemailProvider* aProvider);
|
||||
|
||||
nsISupports*
|
||||
GetParentObject() const { return mParent; }
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL interface
|
||||
|
||||
uint32_t
|
||||
ServiceId() const;
|
||||
|
||||
bool
|
||||
HasMessages() const;
|
||||
|
||||
int32_t
|
||||
MessageCount() const;
|
||||
|
||||
void
|
||||
GetReturnNumber(nsString& aReturnNumber) const;
|
||||
|
||||
void
|
||||
GetReturnMessage(nsString& aReturnMessage) const;
|
||||
|
||||
private:
|
||||
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
|
||||
~VoicemailStatus() {}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
nsCOMPtr<nsIVoicemailProvider> mProvider;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_voicemail_VoicemailStatus_h__
|
260
dom/voicemail/gonk/VoicemailService.js
Normal file
260
dom/voicemail/gonk/VoicemailService.js
Normal file
@ -0,0 +1,260 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
|
||||
let obj = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", obj);
|
||||
return obj;
|
||||
});
|
||||
|
||||
const GONK_VOICEMAIL_SERVICE_CONTRACTID =
|
||||
"@mozilla.org/voicemail/gonkvoicemailservice;1";
|
||||
const GONK_VOICEMAIL_SERVICE_CID =
|
||||
Components.ID("{c332f318-1cce-4f02-b676-bb5031d10736}");
|
||||
|
||||
const NS_MOBILE_CONNECTION_SERVICE_CONTRACTID =
|
||||
"@mozilla.org/mobileconnection/mobileconnectionservice;1";
|
||||
|
||||
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
||||
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
|
||||
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
|
||||
const kPrefDefaultServiceId = "dom.voicemail.defaultServiceId";
|
||||
|
||||
let DEBUG;
|
||||
function debug(s) {
|
||||
dump("VoicemailService: " + s);
|
||||
}
|
||||
|
||||
function VoicemailProvider(aServiceId) {
|
||||
this.serviceId = aServiceId;
|
||||
}
|
||||
VoicemailProvider.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIVoicemailProvider]),
|
||||
|
||||
// nsIVoicemail interface
|
||||
|
||||
serviceId: 0,
|
||||
|
||||
number: null,
|
||||
displayName: null,
|
||||
|
||||
hasMessages: false,
|
||||
messageCount: 0,
|
||||
returnNumber: null,
|
||||
returnMessage: null,
|
||||
};
|
||||
|
||||
function VoicemailService() {
|
||||
// Initialize |this._providers|.
|
||||
let mcService = Cc[NS_MOBILE_CONNECTION_SERVICE_CONTRACTID]
|
||||
.getService(Ci.nsIMobileConnectionService);
|
||||
let numItems = mcService.numItems;
|
||||
this._providers = [];
|
||||
for (let i = 0; i < numItems; i++) {
|
||||
this._providers.push(new VoicemailProvider(i));
|
||||
}
|
||||
|
||||
this._listeners = [];
|
||||
|
||||
// Must be initialized after |this._providers|.
|
||||
this._defaultServiceId = this._getDefaultServiceId();
|
||||
this._updateDebugFlag();
|
||||
|
||||
Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
|
||||
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
|
||||
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
}
|
||||
|
||||
VoicemailService.prototype = {
|
||||
classID: GONK_VOICEMAIL_SERVICE_CID,
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: GONK_VOICEMAIL_SERVICE_CID,
|
||||
contractID: GONK_VOICEMAIL_SERVICE_CONTRACTID,
|
||||
classDescription: "VoicemailService",
|
||||
interfaces: [
|
||||
Ci.nsIVoicemailService,
|
||||
Ci.nsIGonkVoicemailService
|
||||
],
|
||||
flags: Ci.nsIClassInfo.SINGLETON
|
||||
}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIVoicemailService,
|
||||
Ci.nsIGonkVoicemailService,
|
||||
Ci.nsIObserver
|
||||
]),
|
||||
|
||||
_defaultServiceId: null,
|
||||
_providers: null,
|
||||
|
||||
_updateDebugFlag: function() {
|
||||
try {
|
||||
DEBUG = RIL.DEBUG_RIL ||
|
||||
Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
_getDefaultServiceId: function() {
|
||||
let id = Services.prefs.getIntPref(kPrefDefaultServiceId);
|
||||
if (id >= this.numItems || id < 0) {
|
||||
id = 0;
|
||||
}
|
||||
|
||||
return id;
|
||||
},
|
||||
|
||||
_listeners: null,
|
||||
|
||||
_notifyListeners: function(aMethodName, aItem) {
|
||||
let listeners = this._listeners.slice();
|
||||
for (let listener of listeners) {
|
||||
try {
|
||||
listener[aMethodName].call(listener, aItem);
|
||||
} catch (e) {
|
||||
if (DEBUG) {
|
||||
debug("listener for " + aMethodName + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIVoicemailService interface
|
||||
*/
|
||||
|
||||
get numItems() {
|
||||
return this._providers.length;
|
||||
},
|
||||
|
||||
getItemByServiceId: function(aServiceId) {
|
||||
let provider = this._providers[aServiceId];
|
||||
if (!provider) {
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return provider;
|
||||
},
|
||||
|
||||
getDefaultItem: function() {
|
||||
return this.getItemByServiceId(this._defaultServiceId);
|
||||
},
|
||||
|
||||
registerListener: function(aListener) {
|
||||
if (this._listeners.indexOf(aListener) >= 0) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
this._listeners.push(aListener);
|
||||
},
|
||||
|
||||
unregisterListener: function(aListener) {
|
||||
let index = this._listeners.indexOf(aListener);
|
||||
if (index < 0) {
|
||||
return Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
this._listeners.splice(index, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIGonkVoicemailService interface
|
||||
*/
|
||||
|
||||
notifyStatusChanged: function(aServiceId, aHasMessages, aMessageCount,
|
||||
aReturnNumber, aReturnMessage) {
|
||||
if (DEBUG) {
|
||||
debug("notifyStatusChanged: " +
|
||||
JSON.stringify(Array.prototype.slice.call(arguments)));
|
||||
}
|
||||
|
||||
let provider = this.getItemByServiceId(aServiceId);
|
||||
|
||||
let changed = false;
|
||||
if (provider.hasMessages != aHasMessages) {
|
||||
provider.hasMessages = aHasMessages;
|
||||
changed = true;
|
||||
}
|
||||
if (provider.messageCount != aMessageCount) {
|
||||
provider.messageCount = aMessageCount;
|
||||
changed = true;
|
||||
} else if (aMessageCount == -1) {
|
||||
// For MWI using DCS the message count is not available
|
||||
changed = true;
|
||||
}
|
||||
if (provider.returnNumber != aReturnNumber) {
|
||||
provider.returnNumber = aReturnNumber;
|
||||
changed = true;
|
||||
}
|
||||
if (provider.returnMessage != aReturnMessage) {
|
||||
provider.returnMessage = aReturnMessage;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this._notifyListeners("notifyStatusChanged", provider);
|
||||
}
|
||||
},
|
||||
|
||||
notifyInfoChanged: function(aServiceId, aNumber, aDisplayName) {
|
||||
if (DEBUG) {
|
||||
debug("notifyInfoChanged: " +
|
||||
JSON.stringify(Array.prototype.slice.call(arguments)));
|
||||
}
|
||||
|
||||
let provider = this.getItemByServiceId(aServiceId);
|
||||
|
||||
let changed = false;
|
||||
if (provider.number != aNumber) {
|
||||
provider.number = aNumber;
|
||||
changed = true;
|
||||
}
|
||||
if (provider.displayName != aDisplayName) {
|
||||
provider.displayName = aDisplayName;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this._notifyListeners("notifyInfoChanged", provider);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver interface.
|
||||
*/
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
|
||||
if (aData === kPrefRilDebuggingEnabled) {
|
||||
this._updateDebugFlag();
|
||||
} else if (aData === kPrefDefaultServiceId) {
|
||||
this._defaultServiceId = this._getDefaultServiceId();
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
|
||||
Services.prefs.removeObserver(kPrefRilDebuggingEnabled, this);
|
||||
Services.prefs.removeObserver(kPrefDefaultServiceId, this);
|
||||
|
||||
Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
|
||||
// Remove all listeners.
|
||||
this._listeners = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([VoicemailService]);
|
7
dom/voicemail/gonk/VoicemailService.manifest
Normal file
7
dom/voicemail/gonk/VoicemailService.manifest
Normal file
@ -0,0 +1,7 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
component {c332f318-1cce-4f02-b676-bb5031d10736} VoicemailService.js
|
||||
contract @mozilla.org/voicemail/gonkvoicemailservice;1 {c332f318-1cce-4f02-b676-bb5031d10736}
|
||||
|
30
dom/voicemail/gonk/nsIGonkVoicemailService.idl
Normal file
30
dom/voicemail/gonk/nsIGonkVoicemailService.idl
Normal file
@ -0,0 +1,30 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIVoicemailService.idl"
|
||||
|
||||
%{C++
|
||||
#define GONK_VOICEMAIL_SERVICE_CONTRACTID \
|
||||
"@mozilla.org/voicemail/gonkvoicemailservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(d21dbc55-f540-417d-aa3e-9e890764e957)]
|
||||
interface nsIGonkVoicemailService : nsIVoicemailService
|
||||
{
|
||||
/**
|
||||
* Called when a voicemail notification has been received by the network.
|
||||
*/
|
||||
void notifyStatusChanged(in unsigned long serviceId,
|
||||
in bool hasMessages,
|
||||
in long messageCount,
|
||||
in DOMString returnNumber,
|
||||
in DOMString returnMessage);
|
||||
|
||||
/**
|
||||
* Called when other voicemail attributes changed.
|
||||
*/
|
||||
void notifyInfoChanged(in unsigned long serviceId,
|
||||
in DOMString number,
|
||||
in DOMString displayName);
|
||||
};
|
45
dom/voicemail/ipc/PVoicemail.ipdl
Normal file
45
dom/voicemail/ipc/PVoicemail.ipdl
Normal file
@ -0,0 +1,45 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PContent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace voicemail {
|
||||
|
||||
sync protocol PVoicemail
|
||||
{
|
||||
manager PContent;
|
||||
|
||||
child:
|
||||
NotifyInfoChanged(uint32_t aServiceId,
|
||||
nsString aNumber,
|
||||
nsString aDisplayName);
|
||||
|
||||
NotifyStatusChanged(uint32_t aServiceId,
|
||||
bool aHasMessages,
|
||||
int32_t aMessageCount,
|
||||
nsString aNumber,
|
||||
nsString aDisplayName);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Send when child no longer needs to use PVoicemail.
|
||||
*/
|
||||
__delete__();
|
||||
|
||||
sync GetAttributes(uint32_t aServiceId)
|
||||
returns (nsString aNumber,
|
||||
nsString aDisplayName,
|
||||
bool aHasMessages,
|
||||
int32_t aMessageCount,
|
||||
nsString aReturnNumber,
|
||||
nsString aReturnMessage);
|
||||
};
|
||||
|
||||
} // namespace voicemail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
261
dom/voicemail/ipc/VoicemailIPCService.cpp
Normal file
261
dom/voicemail/ipc/VoicemailIPCService.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/voicemail/VoicemailIPCService.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIMobileConnectionService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace voicemail {
|
||||
|
||||
class VoicemailIPCProvider MOZ_FINAL : public nsIVoicemailProvider
|
||||
{
|
||||
friend class VoicemailIPCService;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIVOICEMAILPROVIDER
|
||||
|
||||
VoicemailIPCProvider(uint32_t aServiceId);
|
||||
|
||||
private:
|
||||
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
|
||||
~VoicemailIPCProvider() {}
|
||||
|
||||
private:
|
||||
uint32_t mServiceId;
|
||||
nsString mNumber;
|
||||
nsString mDisplayName;
|
||||
bool mHasMessages;
|
||||
int32_t mMessageCount;
|
||||
nsString mReturnNumber;
|
||||
nsString mReturnMessage;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(VoicemailIPCProvider, nsIVoicemailProvider)
|
||||
|
||||
VoicemailIPCProvider::VoicemailIPCProvider(uint32_t aServiceId)
|
||||
: mServiceId(aServiceId)
|
||||
, mHasMessages(false)
|
||||
, mMessageCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
// nsIVoicemailProvider
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetServiceId(uint32_t* aServiceId)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aServiceId);
|
||||
|
||||
*aServiceId = mServiceId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetNumber(nsAString& aNumber)
|
||||
{
|
||||
aNumber = mNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetDisplayName(nsAString& aDisplayName)
|
||||
{
|
||||
aDisplayName = mDisplayName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetHasMessages(bool* aHasMessages)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aHasMessages);
|
||||
|
||||
*aHasMessages = mHasMessages;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetMessageCount(int32_t* aMessageCount)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessageCount);
|
||||
|
||||
*aMessageCount = mMessageCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetReturnNumber(nsAString& aReturnNumber)
|
||||
{
|
||||
aReturnNumber = mReturnNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCProvider::GetReturnMessage(nsAString& aReturnMessage)
|
||||
{
|
||||
aReturnMessage = mReturnMessage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(VoicemailIPCService, nsIVoicemailService)
|
||||
|
||||
VoicemailIPCService::VoicemailIPCService()
|
||||
: mActorDestroyed(false)
|
||||
{
|
||||
ContentChild::GetSingleton()->SendPVoicemailConstructor(this);
|
||||
|
||||
nsCOMPtr<nsIMobileConnectionService> mcService =
|
||||
do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
|
||||
if (mcService) {
|
||||
uint32_t length = 0;
|
||||
if (NS_SUCCEEDED(mcService->GetNumItems(&length))) {
|
||||
mProviders.SetLength(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoicemailIPCService::~VoicemailIPCService()
|
||||
{
|
||||
if (!mActorDestroyed) {
|
||||
Send__delete__(this);
|
||||
}
|
||||
}
|
||||
|
||||
// PVoicemailChild
|
||||
|
||||
bool
|
||||
VoicemailIPCService::RecvNotifyInfoChanged(const uint32_t& aServiceId,
|
||||
const nsString& aNumber,
|
||||
const nsString& aDisplayName)
|
||||
{
|
||||
nsCOMPtr<nsIVoicemailProvider> provider;
|
||||
NS_ENSURE_SUCCESS(GetItemByServiceId(aServiceId, getter_AddRefs(provider)), false);
|
||||
|
||||
VoicemailIPCProvider* pProvider =
|
||||
static_cast<VoicemailIPCProvider*>(provider.get());
|
||||
pProvider->mNumber = aNumber;
|
||||
pProvider->mDisplayName = aDisplayName;
|
||||
|
||||
// Listeners may unregister itself upon a info changed event, so we make a
|
||||
// copy first.
|
||||
nsTArray<nsCOMPtr<nsIVoicemailListener>> copy(mListeners);
|
||||
for (uint32_t i = 0; i < copy.Length(); i++) {
|
||||
copy[i]->NotifyInfoChanged(provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
VoicemailIPCService::RecvNotifyStatusChanged(const uint32_t& aServiceId,
|
||||
const bool& aHasMessages,
|
||||
const int32_t& aMessageCount,
|
||||
const nsString& aReturnNumber,
|
||||
const nsString& aReturnMessage)
|
||||
{
|
||||
nsCOMPtr<nsIVoicemailProvider> provider;
|
||||
NS_ENSURE_SUCCESS(GetItemByServiceId(aServiceId, getter_AddRefs(provider)), false);
|
||||
|
||||
VoicemailIPCProvider* pProvider =
|
||||
static_cast<VoicemailIPCProvider*>(provider.get());
|
||||
pProvider->mHasMessages = aHasMessages;
|
||||
pProvider->mMessageCount = aMessageCount;
|
||||
pProvider->mReturnNumber = aReturnNumber;
|
||||
pProvider->mReturnMessage = aReturnMessage;
|
||||
|
||||
// Listeners may unregister itself upon a info changed event, so we make a
|
||||
// copy first.
|
||||
nsTArray<nsCOMPtr<nsIVoicemailListener>> copy(mListeners);
|
||||
for (uint32_t i = 0; i < copy.Length(); i++) {
|
||||
copy[i]->NotifyStatusChanged(provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VoicemailIPCService::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mActorDestroyed = true;
|
||||
}
|
||||
|
||||
// nsIVoicemailService
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCService::GetNumItems(uint32_t* aNumItems)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNumItems);
|
||||
|
||||
*aNumItems = mProviders.Length();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCService::GetItemByServiceId(uint32_t aServiceId,
|
||||
nsIVoicemailProvider** aProvider)
|
||||
{
|
||||
NS_ENSURE_ARG(aServiceId < mProviders.Length());
|
||||
NS_ENSURE_ARG_POINTER(aProvider);
|
||||
|
||||
if (!mProviders[aServiceId]) {
|
||||
nsRefPtr<VoicemailIPCProvider> provider =
|
||||
new VoicemailIPCProvider(aServiceId);
|
||||
if (!SendGetAttributes(aServiceId,
|
||||
&(provider->mNumber),
|
||||
&(provider->mDisplayName),
|
||||
&(provider->mHasMessages),
|
||||
&(provider->mMessageCount),
|
||||
&(provider->mReturnNumber),
|
||||
&(provider->mReturnMessage))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mProviders[aServiceId] = provider;
|
||||
}
|
||||
|
||||
nsRefPtr<nsIVoicemailProvider> provider(mProviders[aServiceId]);
|
||||
provider.forget(aProvider);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCService::GetDefaultItem(nsIVoicemailProvider** aProvider)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProvider);
|
||||
|
||||
int defaultServiceId =
|
||||
Preferences::GetInt("dom.voicemail.defaultServiceId", 0);
|
||||
return GetItemByServiceId(defaultServiceId, aProvider);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCService::RegisterListener(nsIVoicemailListener* aListener)
|
||||
{
|
||||
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_UNEXPECTED);
|
||||
NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED);
|
||||
|
||||
mListeners.AppendElement(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailIPCService::UnregisterListener(nsIVoicemailListener* aListener)
|
||||
{
|
||||
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return mListeners.RemoveElement(aListener) ? NS_OK : NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
} // namespace voicemail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
57
dom/voicemail/ipc/VoicemailIPCService.h
Normal file
57
dom/voicemail/ipc/VoicemailIPCService.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_voicemail_VoicemailIPCService_h
|
||||
#define mozilla_dom_voicemail_VoicemailIPCService_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/voicemail/PVoicemailChild.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIVoicemailService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace voicemail {
|
||||
|
||||
class VoicemailIPCService MOZ_FINAL : public PVoicemailChild
|
||||
, public nsIVoicemailService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIVOICEMAILSERVICE
|
||||
|
||||
VoicemailIPCService();
|
||||
|
||||
bool
|
||||
RecvNotifyInfoChanged(const uint32_t& aServiceId,
|
||||
const nsString& aNumber,
|
||||
const nsString& aDisplayName) MOZ_OVERRIDE;
|
||||
|
||||
bool
|
||||
RecvNotifyStatusChanged(const uint32_t& aServiceId,
|
||||
const bool& aHasMessages,
|
||||
const int32_t& aMessageCount,
|
||||
const nsString& aNumber,
|
||||
const nsString& aDisplayName) MOZ_OVERRIDE;
|
||||
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
|
||||
~VoicemailIPCService();
|
||||
|
||||
private:
|
||||
bool mActorDestroyed;
|
||||
nsTArray<nsCOMPtr<nsIVoicemailListener>> mListeners;
|
||||
nsTArray<nsCOMPtr<nsIVoicemailProvider>> mProviders;
|
||||
};
|
||||
|
||||
} // namespace voicemail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_voicemail_VoicemailIPCService_h
|
92
dom/voicemail/ipc/VoicemailParent.cpp
Normal file
92
dom/voicemail/ipc/VoicemailParent.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/voicemail/VoicemailParent.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace voicemail {
|
||||
|
||||
NS_IMPL_ISUPPORTS(VoicemailParent,
|
||||
nsIVoicemailListener)
|
||||
|
||||
bool
|
||||
VoicemailParent::Init()
|
||||
{
|
||||
mService = do_GetService(NS_VOICEMAIL_SERVICE_CONTRACTID);
|
||||
return mService && NS_SUCCEEDED(mService->RegisterListener(this));
|
||||
}
|
||||
|
||||
bool
|
||||
VoicemailParent::RecvGetAttributes(const uint32_t& aServiceId,
|
||||
nsString* aNumber,
|
||||
nsString* aDisplayName,
|
||||
bool* aHasMessages,
|
||||
int32_t* aMessageCount,
|
||||
nsString* aReturnNumber,
|
||||
nsString* aReturnMessage)
|
||||
{
|
||||
nsCOMPtr<nsIVoicemailProvider> provider;
|
||||
NS_ENSURE_SUCCESS(mService->GetItemByServiceId(aServiceId,
|
||||
getter_AddRefs(provider)), false);
|
||||
|
||||
provider->GetNumber(*aNumber);
|
||||
provider->GetDisplayName(*aDisplayName);
|
||||
provider->GetHasMessages(aHasMessages);
|
||||
provider->GetMessageCount(aMessageCount);
|
||||
provider->GetReturnNumber(*aReturnNumber);
|
||||
provider->GetReturnMessage(*aReturnMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VoicemailParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mService->UnregisterListener(this);
|
||||
mService = nullptr;
|
||||
}
|
||||
|
||||
// nsIVoicemailListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailParent::NotifyInfoChanged(nsIVoicemailProvider* aProvider)
|
||||
{
|
||||
uint32_t serviceId = 0;
|
||||
nsString number, displayName;
|
||||
|
||||
aProvider->GetServiceId(&serviceId);
|
||||
aProvider->GetNumber(number);
|
||||
aProvider->GetDisplayName(displayName);
|
||||
|
||||
return SendNotifyInfoChanged(serviceId, number, displayName)
|
||||
? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VoicemailParent::NotifyStatusChanged(nsIVoicemailProvider* aProvider)
|
||||
{
|
||||
uint32_t serviceId = 0;
|
||||
bool hasMessages = false;
|
||||
int32_t messageCount = 0;
|
||||
nsString returnNumber, returnMessage;
|
||||
|
||||
aProvider->GetServiceId(&serviceId);
|
||||
aProvider->GetHasMessages(&hasMessages);
|
||||
aProvider->GetMessageCount(&messageCount);
|
||||
aProvider->GetReturnNumber(returnNumber);
|
||||
aProvider->GetReturnMessage(returnMessage);
|
||||
|
||||
return SendNotifyStatusChanged(serviceId, hasMessages, messageCount,
|
||||
returnNumber, returnMessage)
|
||||
? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
} // namespace voicemail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
57
dom/voicemail/ipc/VoicemailParent.h
Normal file
57
dom/voicemail/ipc/VoicemailParent.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_voicemail_VoicemailParent_h
|
||||
#define mozilla_dom_voicemail_VoicemailParent_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/voicemail/PVoicemailParent.h"
|
||||
#include "mozilla/dom/voicemail/VoicemailParent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIVoicemailService.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace voicemail {
|
||||
|
||||
class VoicemailParent MOZ_FINAL : public PVoicemailParent
|
||||
, public nsIVoicemailListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIVOICEMAILLISTENER
|
||||
|
||||
VoicemailParent() { MOZ_COUNT_CTOR(VoicemailParent); }
|
||||
|
||||
bool
|
||||
Init();
|
||||
|
||||
bool
|
||||
RecvGetAttributes(const uint32_t& aServiceId,
|
||||
nsString* aNumber,
|
||||
nsString* aDisplayName,
|
||||
bool* aHasMessages,
|
||||
int32_t* aMessageCount,
|
||||
nsString* aReturnNumber,
|
||||
nsString* aReturnMessage) MOZ_OVERRIDE;
|
||||
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
|
||||
~VoicemailParent() { MOZ_COUNT_DTOR(VoicemailParent); }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIVoicemailService> mService;
|
||||
};
|
||||
|
||||
} // namespace voicemail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_voicemail_VoicemailParent_h
|
@ -5,23 +5,51 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIVoicemailProvider.idl',
|
||||
'nsIVoicemailService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_voicemail'
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Voicemail.h',
|
||||
'VoicemailStatus.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom.voicemail += [
|
||||
'ipc/VoicemailIPCService.h',
|
||||
'ipc/VoicemailParent.h',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'ipc/PVoicemail.ipdl',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'ipc/VoicemailIPCService.cpp',
|
||||
'ipc/VoicemailParent.cpp',
|
||||
'Voicemail.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'VoicemailStatus.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
XPIDL_SOURCES += [
|
||||
'gonk/nsIGonkVoicemailService.idl',
|
||||
]
|
||||
EXTRA_COMPONENTS += [
|
||||
'gonk/VoicemailService.js',
|
||||
'gonk/VoicemailService.manifest',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../base',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -1,39 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(214b0963-da48-4859-a56c-f065a90e0403)]
|
||||
interface nsIVoicemailListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called when a voicemail notification has been received by the network.
|
||||
*
|
||||
* @param status
|
||||
* The new voicemail status
|
||||
*/
|
||||
void notifyStatusChanged(in jsval status);
|
||||
};
|
||||
|
||||
/**
|
||||
* XPCOM component (in the content process) that provides the voicemail
|
||||
* information.
|
||||
*/
|
||||
[scriptable, uuid(1bbfff90-88f7-4d73-896e-9620a0000ab0)]
|
||||
interface nsIVoicemailProvider : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long voicemailDefaultServiceId;
|
||||
|
||||
/**
|
||||
* Called when a content process registers receiving unsolicited messages from
|
||||
* RadioInterfaceLayer in the chrome process. Only a content process that has
|
||||
* the 'voicemail' permission is allowed to register.
|
||||
*/
|
||||
void registerVoicemailMsg(in nsIVoicemailListener listener);
|
||||
void unregisterVoicemailMsg(in nsIVoicemailListener listener);
|
||||
|
||||
jsval getVoicemailStatus(in unsigned long clientId);
|
||||
DOMString getVoicemailNumber(in unsigned long clientId);
|
||||
DOMString getVoicemailDisplayName(in unsigned long clientId);
|
||||
};
|
137
dom/voicemail/nsIVoicemailService.idl
Normal file
137
dom/voicemail/nsIVoicemailService.idl
Normal file
@ -0,0 +1,137 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIVoicemailProvider;
|
||||
|
||||
[scriptable, uuid(6a8b0133-960d-409d-88cd-583239e45f9f)]
|
||||
interface nsIVoicemailListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called when a voicemail status (hasMessages, messageCount, returnNumber,
|
||||
* returnMessage) changed.
|
||||
*/
|
||||
void notifyStatusChanged(in nsIVoicemailProvider provider);
|
||||
|
||||
/**
|
||||
* Called when a voicemail info (number, displayName) changed.
|
||||
*/
|
||||
void notifyInfoChanged(in nsIVoicemailProvider provider);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_VOICEMAIL_SERVICE_CID \
|
||||
{ 0xcdd8fd72, 0x7d55, 0x496b, \
|
||||
{ 0xab, 0x1d, 0x74, 0x9f, 0xbc, 0x44, 0x56, 0x32 } }
|
||||
#define NS_VOICEMAIL_SERVICE_CONTRACTID \
|
||||
"@mozilla.org/voicemail/voicemailservice;1"
|
||||
%}
|
||||
|
||||
/**
|
||||
* XPCOM component (in the content process) that provides the voicemail
|
||||
* information.
|
||||
*/
|
||||
[scriptable, uuid(8ffd16c7-a614-4c4a-81f0-2a95e807152d)]
|
||||
interface nsIVoicemailService : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long numItems;
|
||||
|
||||
nsIVoicemailProvider getItemByServiceId(in unsigned long serviceId);
|
||||
|
||||
nsIVoicemailProvider getDefaultItem();
|
||||
|
||||
/**
|
||||
* Called when any one who is interested in receiving unsolicited messages.
|
||||
*/
|
||||
void registerListener(in nsIVoicemailListener listener);
|
||||
void unregisterListener(in nsIVoicemailListener listener);
|
||||
};
|
||||
|
||||
%{C++
|
||||
template<typename T> struct already_AddRefed;
|
||||
|
||||
already_AddRefed<nsIVoicemailService>
|
||||
NS_CreateVoicemailService();
|
||||
%}
|
||||
|
||||
[scriptable, uuid(a0bc19a2-3216-4f3f-89d3-8976a48cb829)]
|
||||
interface nsIVoicemailProvider : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long serviceId;
|
||||
|
||||
/**
|
||||
* Voicemail center number. When changed, |notifyInfoChanged| of registered
|
||||
* nsIVoicemailListener instances are called.
|
||||
*
|
||||
* Default: null
|
||||
*
|
||||
* @see 3GPP TS 31.102 subclause 4.2.63 "EFmwis (Message Waiting Indication Status)"
|
||||
* @see 3GPP TS 51.011 subclause 10.3.45 "EFmwis (Message Waiting Indication Status)"
|
||||
*/
|
||||
readonly attribute DOMString number;
|
||||
|
||||
/**
|
||||
* Voicemail center display name. When changed, |notifyInfoChanged| of
|
||||
* registered nsIVoicemailListener instances are called.
|
||||
*
|
||||
* Default: null
|
||||
*
|
||||
* @see 3GPP TS 31.102 subclause 4.2.63 "EFmwis (Message Waiting Indication Status)"
|
||||
* @see 3GPP TS 51.011 subclause 10.3.45 "EFmwis (Message Waiting Indication Status)"
|
||||
*/
|
||||
readonly attribute DOMString displayName;
|
||||
|
||||
/**
|
||||
* Whether or not there are messages waiting in the voicemail box. When
|
||||
* changed, |notifyStatusChanged| of registered nsIVoicemailListener instances
|
||||
* are called.
|
||||
*
|
||||
* Default: false
|
||||
*
|
||||
* @see 3GPP TS 23.038 chapter 4 "SMS Data Coding Scheme"
|
||||
* @see 3GPP TS 23.040 subclause 9.2.3.24.2 "Special SMS Message Indication"
|
||||
*/
|
||||
readonly attribute boolean hasMessages;
|
||||
|
||||
/**
|
||||
* When #hasMessages is true, #messageCount should be a positive number for
|
||||
* the messages waiting, or -1 if the exact number is not available. When
|
||||
* changed, |notifyStatusChanged| of registered nsIVoicemailListener instances
|
||||
* are called.
|
||||
*
|
||||
* Default: 0
|
||||
*
|
||||
* @see 3GPP TS 23.040 subclause 9.2.3.24.2 "Special SMS Message Indication"
|
||||
*/
|
||||
readonly attribute long messageCount;
|
||||
|
||||
/**
|
||||
* A Return Call Message indicates to the MS to inform the user that a call
|
||||
* (e.g. a telephone call) can be established to the address specified within
|
||||
* the #returnNumber. The #returnMessage (if present) gives displayable
|
||||
* information (e.g. the number of waiting voice messages).
|
||||
*
|
||||
* When #hasMessages is true this may contain a non-null string as the phone
|
||||
* number of a Return Call Message. When changed, |notifyStatusChanged| of
|
||||
* registered nsIVoicemailListener instances are called.
|
||||
*
|
||||
* Default: null
|
||||
*
|
||||
* @see 3GPP TS 23.040 subclause 9.2.3.9 "TPProtocolIdentifier (TPPID)"
|
||||
*/
|
||||
readonly attribute DOMString returnNumber;
|
||||
|
||||
/**
|
||||
* When #hasMessages is true this may contain a non-null string as the
|
||||
* notification message of a Return Call Message. When changed,
|
||||
* |notifyStatusChanged| of registered nsIVoicemailListener instances are
|
||||
* called.
|
||||
*
|
||||
* Default: null
|
||||
*
|
||||
* @see 3GPP TS 23.040 subclause 9.2.3.9 "TPProtocolIdentifier (TPPID)"
|
||||
*/
|
||||
readonly attribute DOMString returnMessage;
|
||||
};
|
415
dom/voicemail/test/marionette/head.js
Normal file
415
dom/voicemail/test/marionette/head.js
Normal file
@ -0,0 +1,415 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
|
||||
|
||||
let RIL = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
|
||||
const MWI_PDU_PREFIX = "0000";
|
||||
const MWI_PDU_UDH_PREFIX = "0040";
|
||||
const MWI_PID_DEFAULT = "00";
|
||||
const MWI_DCS_DISCARD_INACTIVE = "C0";
|
||||
const MWI_DCS_DISCARD_ACTIVE = "C8";
|
||||
const MWI_TIMESTAMP = "00000000000000";
|
||||
|
||||
// Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing
|
||||
// that code turns out to be a nightmare, so there is some code duplication.
|
||||
let PDUBuilder = {
|
||||
toHexString: function(n, length) {
|
||||
let str = n.toString(16);
|
||||
if (str.length < length) {
|
||||
for (let i = 0; i < length - str.length; i++) {
|
||||
str = "0" + str;
|
||||
}
|
||||
}
|
||||
return str.toUpperCase();
|
||||
},
|
||||
|
||||
writeUint16: function(value) {
|
||||
this.buf += (value & 0xff).toString(16).toUpperCase();
|
||||
this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase();
|
||||
},
|
||||
|
||||
writeHexOctet: function(octet) {
|
||||
this.buf += this.toHexString(octet, 2);
|
||||
},
|
||||
|
||||
writeSwappedNibbleBCD: function(data) {
|
||||
data = data.toString();
|
||||
let zeroCharCode = '0'.charCodeAt(0);
|
||||
|
||||
for (let i = 0; i < data.length; i += 2) {
|
||||
let low = data.charCodeAt(i) - zeroCharCode;
|
||||
let high;
|
||||
if (i + 1 < data.length) {
|
||||
high = data.charCodeAt(i + 1) - zeroCharCode;
|
||||
} else {
|
||||
high = 0xF;
|
||||
}
|
||||
|
||||
this.writeHexOctet((high << 4) | low);
|
||||
}
|
||||
},
|
||||
|
||||
writeStringAsSeptets: function(message, paddingBits, langIndex,
|
||||
langShiftIndex) {
|
||||
const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
|
||||
const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
|
||||
|
||||
let dataBits = paddingBits;
|
||||
let data = 0;
|
||||
for (let i = 0; i < message.length; i++) {
|
||||
let septet = langTable.indexOf(message[i]);
|
||||
if (septet == RIL.PDU_NL_EXTENDED_ESCAPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (septet >= 0) {
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
} else {
|
||||
septet = langShiftTable.indexOf(message[i]);
|
||||
if (septet == -1) {
|
||||
throw new Error(message[i] + " not in 7 bit alphabet "
|
||||
+ langIndex + ":" + langShiftIndex + "!");
|
||||
}
|
||||
|
||||
if (septet == RIL.PDU_NL_RESERVED_CONTROL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data |= RIL.PDU_NL_EXTENDED_ESCAPE << dataBits;
|
||||
dataBits += 7;
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
}
|
||||
|
||||
for (; dataBits >= 8; dataBits -= 8) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
data >>>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataBits != 0) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
}
|
||||
},
|
||||
|
||||
buildAddress: function(address) {
|
||||
let addressFormat = RIL.PDU_TOA_ISDN; // 81
|
||||
if (address[0] == '+') {
|
||||
addressFormat = RIL.PDU_TOA_INTERNATIONAL | RIL.PDU_TOA_ISDN; // 91
|
||||
address = address.substring(1);
|
||||
}
|
||||
|
||||
this.buf = "";
|
||||
this.writeHexOctet(address.length);
|
||||
this.writeHexOctet(addressFormat);
|
||||
this.writeSwappedNibbleBCD(address);
|
||||
|
||||
return this.buf;
|
||||
},
|
||||
|
||||
// assumes 7 bit encoding
|
||||
buildUserData: function(options) {
|
||||
let headerLength = 0;
|
||||
this.buf = "";
|
||||
if (options.headers) {
|
||||
for each (let header in options.headers) {
|
||||
headerLength += 2; // id + length octets
|
||||
if (header.octets) {
|
||||
headerLength += header.octets.length;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let encodedBodyLength = options.body.length;
|
||||
let headerOctets = (headerLength ? headerLength + 1 : 0);
|
||||
|
||||
let paddingBits;
|
||||
let userDataLengthInSeptets;
|
||||
let headerSeptets = Math.ceil(headerOctets * 8 / 7);
|
||||
userDataLengthInSeptets = headerSeptets + encodedBodyLength;
|
||||
paddingBits = headerSeptets * 7 - headerOctets * 8;
|
||||
|
||||
this.writeHexOctet(userDataLengthInSeptets);
|
||||
if (options.headers) {
|
||||
this.writeHexOctet(headerLength);
|
||||
|
||||
for each (let header in options.headers) {
|
||||
this.writeHexOctet(header.id);
|
||||
this.writeHexOctet(header.length);
|
||||
|
||||
if (header.octets) {
|
||||
for each (let octet in header.octets) {
|
||||
this.writeHexOctet(octet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.writeStringAsSeptets(options.body, paddingBits,
|
||||
RIL.PDU_NL_IDENTIFIER_DEFAULT,
|
||||
RIL.PDU_NL_IDENTIFIER_DEFAULT);
|
||||
return this.buf;
|
||||
},
|
||||
|
||||
buildLevel2DiscardMwi: function(aActive, aSender, aBody) {
|
||||
return MWI_PDU_PREFIX +
|
||||
this.buildAddress(aSender) +
|
||||
MWI_PID_DEFAULT +
|
||||
(aActive ? MWI_DCS_DISCARD_ACTIVE : MWI_DCS_DISCARD_INACTIVE) +
|
||||
MWI_TIMESTAMP +
|
||||
this.buildUserData({ body: aBody });
|
||||
},
|
||||
|
||||
buildLevel3DiscardMwi: function(aMessageCount, aSender, aBody) {
|
||||
let options = {
|
||||
headers: [{
|
||||
id: RIL.PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION,
|
||||
length: 2,
|
||||
octets: [
|
||||
RIL.PDU_MWI_STORE_TYPE_DISCARD,
|
||||
aMessageCount || 0
|
||||
]
|
||||
}],
|
||||
body: aBody
|
||||
};
|
||||
|
||||
return MWI_PDU_UDH_PREFIX +
|
||||
this.buildAddress(aSender) +
|
||||
MWI_PID_DEFAULT +
|
||||
MWI_DCS_DISCARD_ACTIVE +
|
||||
MWI_TIMESTAMP +
|
||||
this.buildUserData(options);
|
||||
}
|
||||
};
|
||||
|
||||
let pendingEmulatorCmdCount = 0;
|
||||
|
||||
/**
|
||||
* Send emulator command with safe guard.
|
||||
*
|
||||
* We should only call |finish()| after all emulator command transactions
|
||||
* end, so here comes with the pending counter. Resolve when the emulator
|
||||
* gives positive response, and reject otherwise.
|
||||
*
|
||||
* Fulfill params:
|
||||
* result -- an array of emulator response lines.
|
||||
*
|
||||
* Reject params:
|
||||
* result -- an array of emulator response lines.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function runEmulatorCmdSafe(aCommand) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
++pendingEmulatorCmdCount;
|
||||
runEmulatorCmd(aCommand, function(aResult) {
|
||||
--pendingEmulatorCmdCount;
|
||||
|
||||
ok(true, "Emulator response: " + JSON.stringify(aResult));
|
||||
if (Array.isArray(aResult) && aResult[0] === "OK") {
|
||||
deferred.resolve(aResult);
|
||||
} else {
|
||||
deferred.reject(aResult);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise wrapper for |SpecialPowers.pushPermissions|.
|
||||
*
|
||||
* Fulfill params: a MozVoicemail object.
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aPermissions
|
||||
* A permission operation description array. See
|
||||
* |SpecialPowers.pushPermissions| for more details.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function pushPermissions(aPermissions) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
SpecialPowers.pushPermissions(aPermissions, function() {
|
||||
ok(true, "permissions pushed: " + JSON.stringify(aPermissions));
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
let voicemail;
|
||||
|
||||
/**
|
||||
* Add required permissions and test if |navigator.mozVoicemail| exists.
|
||||
*
|
||||
* Fulfill params: a MozVoicemail object.
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function ensureVoicemail() {
|
||||
let permissions = [{
|
||||
"type": "voicemail",
|
||||
"allow": 1,
|
||||
"context": document,
|
||||
}];
|
||||
|
||||
return pushPermissions(permissions)
|
||||
.then(function() {
|
||||
voicemail = window.navigator.mozVoicemail;
|
||||
if (voicemail == null) {
|
||||
throw "navigator.mozVoicemail is undefined.";
|
||||
}
|
||||
|
||||
if (!(voicemail instanceof MozVoicemail)) {
|
||||
throw "navigator.mozVoicemail is instance of " + voicemail.constructor;
|
||||
}
|
||||
|
||||
return voicemail;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for one named voicemail event.
|
||||
*
|
||||
* Resolve if that named event occurs. Never reject.
|
||||
*
|
||||
* Fulfill params: the DOMEvent passed.
|
||||
*
|
||||
* @param aEventName
|
||||
* A string event name.
|
||||
* @param aMatchFunc [optional]
|
||||
* An additional callback function to match the interested event
|
||||
* before removing the listener and going to resolve the promise.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function waitForManagerEvent(aEventName, aMatchFunc) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
voicemail.addEventListener(aEventName, function onevent(aEvent) {
|
||||
if (aMatchFunc && !aMatchFunc(aEvent)) {
|
||||
ok(true, "MozVoicemail event '" + aEventName + "' got" +
|
||||
" but is not interested.");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(true, "MozVoicemail event '" + aEventName + "' got.");
|
||||
voicemail.removeEventListener(aEventName, onevent);
|
||||
deferred.resolve(aEvent);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send raw voicemail indicator PDU. Resolve if the indicator PDU was sent with
|
||||
* success.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function sendIndicatorPDU(aPDU) {
|
||||
return runEmulatorCmdSafe("sms pdu " + aPDU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send raw voicemail indicator PDU and wait for "statuschanged" event. Resolve
|
||||
* if the indicator was sent and a "statuschanged" event was dispatched to
|
||||
* |navigator.mozVoicemail|.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function sendIndicatorPDUAndWait(aPDU) {
|
||||
let promises = [];
|
||||
|
||||
promises.push(waitForManagerEvent("statuschanged"));
|
||||
promises.push(sendIndicatorPDU(aPDU));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check equalities of all attributes of two VoicemailStatus instances.
|
||||
*/
|
||||
function compareVoicemailStatus(aStatus1, aStatus2) {
|
||||
is(aStatus1.serviceId, aStatus2.serviceId, "VoicemailStatus::serviceId");
|
||||
is(aStatus1.hasMessages, aStatus2.hasMessages, "VoicemailStatus::hasMessages");
|
||||
is(aStatus1.messageCount, aStatus2.messageCount, "VoicemailStatus::messageCount");
|
||||
is(aStatus1.returnNumber, aStatus2.returnNumber, "VoicemailStatus::returnNumber");
|
||||
is(aStatus1.returnMessage, aStatus2.returnMessage, "VoicemailStatus::returnMessage");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if attributs of a VoicemailStatus match our expectations.
|
||||
*/
|
||||
function checkVoicemailStatus(aStatus, aServiceId, aHasMessages, aMessageCount,
|
||||
aReturnNumber, aReturnMessage) {
|
||||
compareVoicemailStatus(aStatus, {
|
||||
serviceId: aServiceId,
|
||||
hasMessages: aHasMessages,
|
||||
messageCount: aMessageCount,
|
||||
returnNumber: aReturnNumber,
|
||||
returnMessage: aReturnMessage
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for pending emulator transactions and call |finish()|.
|
||||
*/
|
||||
function cleanUp() {
|
||||
ok(true, ":: CLEANING UP ::");
|
||||
|
||||
waitFor(finish, function() {
|
||||
return pendingEmulatorCmdCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test routine helper for voicemail tests.
|
||||
*
|
||||
* This helper does nothing but clean-ups.
|
||||
*
|
||||
* @param aTestCaseMain
|
||||
* A function that takes no parameter.
|
||||
*/
|
||||
function startTestBase(aTestCaseMain) {
|
||||
Promise.resolve()
|
||||
.then(aTestCaseMain)
|
||||
.then(cleanUp, function() {
|
||||
ok(false, 'promise rejects during test.');
|
||||
cleanUp();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Common test routine helper for voicemail tests.
|
||||
*
|
||||
* This function ensures global |voicemail| variable is available during the
|
||||
* process and performs clean-ups as well.
|
||||
*
|
||||
* @param aTestCaseMain
|
||||
* A function that takes no parameter.
|
||||
*/
|
||||
function startTestCommon(aTestCaseMain) {
|
||||
startTestBase(function() {
|
||||
return ensureVoicemail()
|
||||
.then(aTestCaseMain);
|
||||
});
|
||||
}
|
@ -3,6 +3,6 @@ b2g = true
|
||||
browser = false
|
||||
qemu = true
|
||||
|
||||
[test_voicemail_statuschanged.py]
|
||||
[test_voicemail_statuschanged.js]
|
||||
[test_voicemail_number.js]
|
||||
[test_dsds_default_service_id.js]
|
||||
|
@ -1,149 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
let RIL = {};
|
||||
SpecialPowers.Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
// Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing
|
||||
// that code turns out to be a nightmare, so there is some code duplication.
|
||||
let PDUBuilder = {
|
||||
toHexString: function(n, length) {
|
||||
let str = n.toString(16);
|
||||
if (str.length < length) {
|
||||
for (let i = 0; i < length - str.length; i++) {
|
||||
str = "0" + str;
|
||||
}
|
||||
}
|
||||
return str.toUpperCase();
|
||||
},
|
||||
|
||||
writeUint16: function(value) {
|
||||
this.buf += (value & 0xff).toString(16).toUpperCase();
|
||||
this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase();
|
||||
},
|
||||
|
||||
writeHexOctet: function(octet) {
|
||||
this.buf += this.toHexString(octet, 2);
|
||||
},
|
||||
|
||||
writeSwappedNibbleBCD: function(data) {
|
||||
data = data.toString();
|
||||
let zeroCharCode = '0'.charCodeAt(0);
|
||||
|
||||
for (let i = 0; i < data.length; i += 2) {
|
||||
let low = data.charCodeAt(i) - zeroCharCode;
|
||||
let high;
|
||||
if (i + 1 < data.length) {
|
||||
high = data.charCodeAt(i + 1) - zeroCharCode;
|
||||
} else {
|
||||
high = 0xF;
|
||||
}
|
||||
|
||||
this.writeHexOctet((high << 4) | low);
|
||||
}
|
||||
},
|
||||
|
||||
writeStringAsSeptets: function(message, paddingBits, langIndex,
|
||||
langShiftIndex) {
|
||||
const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
|
||||
const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
|
||||
|
||||
let dataBits = paddingBits;
|
||||
let data = 0;
|
||||
for (let i = 0; i < message.length; i++) {
|
||||
let septet = langTable.indexOf(message[i]);
|
||||
if (septet == RIL.PDU_NL_EXTENDED_ESCAPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (septet >= 0) {
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
} else {
|
||||
septet = langShiftTable.indexOf(message[i]);
|
||||
if (septet == -1) {
|
||||
throw new Error(message[i] + " not in 7 bit alphabet "
|
||||
+ langIndex + ":" + langShiftIndex + "!");
|
||||
}
|
||||
|
||||
if (septet == RIL.PDU_NL_RESERVED_CONTROL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data |= RIL.PDU_NL_EXTENDED_ESCAPE << dataBits;
|
||||
dataBits += 7;
|
||||
data |= septet << dataBits;
|
||||
dataBits += 7;
|
||||
}
|
||||
|
||||
for (; dataBits >= 8; dataBits -= 8) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
data >>>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataBits != 0) {
|
||||
this.writeHexOctet(data & 0xFF);
|
||||
}
|
||||
},
|
||||
|
||||
buildAddress: function(address) {
|
||||
let addressFormat = RIL.PDU_TOA_ISDN; // 81
|
||||
if (address[0] == '+') {
|
||||
addressFormat = RIL.PDU_TOA_INTERNATIONAL | RIL.PDU_TOA_ISDN; // 91
|
||||
address = address.substring(1);
|
||||
}
|
||||
|
||||
this.buf = "";
|
||||
this.writeHexOctet(address.length);
|
||||
this.writeHexOctet(addressFormat);
|
||||
this.writeSwappedNibbleBCD(address);
|
||||
|
||||
return this.buf;
|
||||
},
|
||||
|
||||
// assumes 7 bit encoding
|
||||
buildUserData: function(options) {
|
||||
let headerLength = 0;
|
||||
this.buf = "";
|
||||
if (options.headers) {
|
||||
for each (let header in options.headers) {
|
||||
headerLength += 2; // id + length octets
|
||||
if (header.octets) {
|
||||
headerLength += header.octets.length;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let encodedBodyLength = options.body.length;
|
||||
let headerOctets = (headerLength ? headerLength + 1 : 0);
|
||||
|
||||
let paddingBits;
|
||||
let userDataLengthInSeptets;
|
||||
let headerSeptets = Math.ceil(headerOctets * 8 / 7);
|
||||
userDataLengthInSeptets = headerSeptets + encodedBodyLength;
|
||||
paddingBits = headerSeptets * 7 - headerOctets * 8;
|
||||
|
||||
this.writeHexOctet(userDataLengthInSeptets);
|
||||
if (options.headers) {
|
||||
this.writeHexOctet(headerLength);
|
||||
|
||||
for each (let header in options.headers) {
|
||||
this.writeHexOctet(header.id);
|
||||
this.writeHexOctet(header.length);
|
||||
|
||||
if (header.octets) {
|
||||
for each (let octet in header.octets) {
|
||||
this.writeHexOctet(octet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.writeStringAsSeptets(options.body, paddingBits,
|
||||
RIL.PDU_NL_IDENTIFIER_DEFAULT,
|
||||
RIL.PDU_NL_IDENTIFIER_DEFAULT);
|
||||
return this.buf;
|
||||
}
|
||||
};
|
@ -6,20 +6,21 @@ MARIONETTE_CONTEXT = "chrome";
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
const VOICEMAIL_PROVIDER_CONTRACTID = "@mozilla.org/ril/content-helper;1";
|
||||
const VOICEMAIL_SERVICE_CONTRACTID =
|
||||
"@mozilla.org/voicemail/gonkvoicemailservice;1";
|
||||
|
||||
const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces";
|
||||
const PREF_DEFAULT_SERVICE_ID = "dom.voicemail.defaultServiceId";
|
||||
|
||||
function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) {
|
||||
function setPrefAndVerify(prefKey, setVal, service, expectedVal, deferred) {
|
||||
log(" Set '" + prefKey + "' to " + setVal);
|
||||
Services.prefs.setIntPref(prefKey, setVal);
|
||||
let prefVal = Services.prefs.getIntPref(prefKey);
|
||||
is(prefVal, setVal, "'" + prefKey + "' set to " + setVal);
|
||||
|
||||
window.setTimeout(function() {
|
||||
let defaultVal = service[attrName];
|
||||
is(defaultVal, expectedVal, attrName);
|
||||
let defaultVal = service.getDefaultItem().serviceId;
|
||||
is(defaultVal, expectedVal, "serviceId");
|
||||
|
||||
deferred.resolve(service);
|
||||
}, 0);
|
||||
@ -52,7 +53,7 @@ function getService(contractId, ifaceName) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkInitialEquality(attrName, prefKey, service) {
|
||||
function checkInitialEquality(prefKey, service) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
log(" Checking initial value for '" + prefKey + "'");
|
||||
@ -60,8 +61,8 @@ function checkInitialEquality(attrName, prefKey, service) {
|
||||
ok(isFinite(origPrefVal), "default '" + prefKey + "' value");
|
||||
|
||||
window.setTimeout(function() {
|
||||
let defaultVal = service[attrName];
|
||||
is(defaultVal, origPrefVal, attrName);
|
||||
let defaultVal = service.getDefaultItem().serviceId;
|
||||
is(defaultVal, origPrefVal, "serviceId");
|
||||
|
||||
deferred.resolve(service);
|
||||
}, 0);
|
||||
@ -69,30 +70,30 @@ function checkInitialEquality(attrName, prefKey, service) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkSetToNegtiveValue(attrName, prefKey, service) {
|
||||
function checkSetToNegtiveValue(prefKey, service) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Set to -1 and verify defaultVal == 0.
|
||||
setPrefAndVerify(prefKey, -1, service, attrName, 0, deferred);
|
||||
setPrefAndVerify(prefKey, -1, service, 0, deferred);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkSetToOverflowedValue(attrName, prefKey, numRil, service) {
|
||||
function checkSetToOverflowedValue(prefKey, numRil, service) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Set to larger-equal than numRil and verify defaultVal == 0.
|
||||
setPrefAndVerify(prefKey, numRil, service, attrName, 0, deferred);
|
||||
setPrefAndVerify(prefKey, numRil, service, 0, deferred);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkValueChange(attrName, prefKey, numRil, service) {
|
||||
function checkValueChange(prefKey, numRil, service) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
if (numRil > 1) {
|
||||
// Set to (numRil - 1) and verify defaultVal equals.
|
||||
setPrefAndVerify(prefKey, numRil - 1, service, attrName, numRil - 1, deferred);
|
||||
setPrefAndVerify(prefKey, numRil - 1, service, numRil - 1, deferred);
|
||||
} else {
|
||||
window.setTimeout(function() {
|
||||
deferred.resolve(service);
|
||||
@ -102,14 +103,14 @@ function checkValueChange(attrName, prefKey, numRil, service) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function verify(contractId, ifaceName, attrName, prefKey, numRil) {
|
||||
function verify(contractId, ifaceName, prefKey, numRil) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
getService(contractId, ifaceName)
|
||||
.then(checkInitialEquality.bind(null, attrName, prefKey))
|
||||
.then(checkSetToNegtiveValue.bind(null, attrName, prefKey))
|
||||
.then(checkSetToOverflowedValue.bind(null, attrName, prefKey, numRil))
|
||||
.then(checkValueChange.bind(null, attrName, prefKey, numRil))
|
||||
.then(checkInitialEquality.bind(null, prefKey))
|
||||
.then(checkSetToNegtiveValue.bind(null, prefKey))
|
||||
.then(checkSetToOverflowedValue.bind(null, prefKey, numRil))
|
||||
.then(checkValueChange.bind(null, prefKey, numRil))
|
||||
.then(function() {
|
||||
// Reset.
|
||||
Services.prefs.clearUserPref(prefKey);
|
||||
@ -121,6 +122,6 @@ function verify(contractId, ifaceName, attrName, prefKey, numRil) {
|
||||
}
|
||||
|
||||
getNumRadioInterfaces()
|
||||
.then(verify.bind(null, VOICEMAIL_PROVIDER_CONTRACTID, "nsIVoicemailProvider",
|
||||
"voicemailDefaultServiceId", PREF_DEFAULT_SERVICE_ID))
|
||||
.then(verify.bind(null, VOICEMAIL_SERVICE_CONTRACTID, "nsIVoicemailService",
|
||||
PREF_DEFAULT_SERVICE_ID))
|
||||
.then(finish);
|
||||
|
@ -1,21 +1,16 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
const MARIONETTE_TIMEOUT = 60000;
|
||||
const MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
SpecialPowers.addPermission("voicemail", true, document);
|
||||
startTestCommon(function() {
|
||||
let serviceId = 0;
|
||||
|
||||
let voicemail = window.navigator.mozVoicemail;
|
||||
ok(voicemail instanceof MozVoicemail);
|
||||
// These are the emulator's hard coded voicemail number and alphaId
|
||||
is(voicemail.getNumber(serviceId), "+15552175049");
|
||||
is(voicemail.getDisplayName(serviceId), "Voicemail");
|
||||
|
||||
let serviceId = 0;
|
||||
|
||||
// These are the emulator's hard coded voicemail number and alphaId
|
||||
is(voicemail.getNumber(serviceId), "+15552175049");
|
||||
is(voicemail.getDisplayName(serviceId), "Voicemail");
|
||||
|
||||
is(voicemail.getNumber(), "+15552175049");
|
||||
is(voicemail.getDisplayName(), "Voicemail");
|
||||
|
||||
SpecialPowers.removePermission("voicemail", document);
|
||||
finish();
|
||||
is(voicemail.getNumber(), "+15552175049");
|
||||
is(voicemail.getDisplayName(), "Voicemail");
|
||||
});
|
||||
|
@ -1,208 +1,60 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
SpecialPowers.addPermission("voicemail", true, document);
|
||||
|
||||
let voicemail = window.navigator.mozVoicemail;
|
||||
let serviceId = 0;
|
||||
|
||||
ok(voicemail instanceof MozVoicemail);
|
||||
is(voicemail.status, null);
|
||||
|
||||
function sendIndicatorPDU(pdu, listener, nextTest) {
|
||||
let smsCommand = "sms pdu " + pdu;
|
||||
let commandCompleted = false;
|
||||
let sawEvent = false;
|
||||
|
||||
voicemail.addEventListener("statuschanged", function statusChanged(event) {
|
||||
voicemail.removeEventListener("statuschanged", statusChanged);
|
||||
|
||||
try {
|
||||
listener(event);
|
||||
} catch (e) {
|
||||
ok(false, String(e));
|
||||
}
|
||||
|
||||
sawEvent = true;
|
||||
if (commandCompleted) {
|
||||
nextTest();
|
||||
}
|
||||
});
|
||||
|
||||
log("-> " + smsCommand);
|
||||
runEmulatorCmd(smsCommand, function(result) {
|
||||
log("<- " + result);
|
||||
is(result[0], "OK");
|
||||
commandCompleted = true;
|
||||
if (sawEvent) {
|
||||
nextTest();
|
||||
}
|
||||
});
|
||||
}
|
||||
const MARIONETTE_TIMEOUT = 60000;
|
||||
const MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
// TODO: Add tests for store/discard once they are implemented
|
||||
// See RadioInterfaceLayer.js / Bug #768441
|
||||
|
||||
function isVoicemailStatus(status) {
|
||||
is(voicemail.getStatus(), status);
|
||||
is(voicemail.getStatus(serviceId), status);
|
||||
function checkEventStatus(aEvent, aServiceId, aHasMessages, aMessageCount,
|
||||
aReturnNumber, aReturnMessage) {
|
||||
let status = aEvent.status;
|
||||
ok(true, "status = " + JSON.stringify(status));
|
||||
ok(status instanceof MozVoicemailStatus);
|
||||
|
||||
is(voicemail.getStatus().hasMessages, status.hasMessages);
|
||||
is(voicemail.getStatus().messageCount, status.messageCount);
|
||||
is(voicemail.getStatus().returnNumber, status.returnNumber);
|
||||
is(voicemail.getStatus().returnMessage, status.returnMessage);
|
||||
checkVoicemailStatus(status, 0, aHasMessages, aMessageCount, aReturnNumber,
|
||||
aReturnMessage);
|
||||
|
||||
compareVoicemailStatus(voicemail.getStatus(0), status);
|
||||
compareVoicemailStatus(voicemail.getStatus(), status);
|
||||
}
|
||||
|
||||
const MWI_PDU_PREFIX = "0000";
|
||||
const MWI_PDU_UDH_PREFIX = "0040";
|
||||
const MWI_PID_DEFAULT = "00";
|
||||
const MWI_DCS_DISCARD_INACTIVE = "C0";
|
||||
const MWI_DCS_DISCARD_ACTIVE = "C8";
|
||||
const MWI_TIMESTAMP = "00000000000000";
|
||||
|
||||
const MWI_DEFAULT_BODY = "1 new voicemail";
|
||||
const MWI_UD_DEFAULT = PDUBuilder.buildUserData({
|
||||
body: MWI_DEFAULT_BODY
|
||||
});
|
||||
|
||||
const MWI_LEVEL2_SENDER = "+15125551235";
|
||||
const MWI_LEVEL2_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL2_SENDER);
|
||||
const MWI_LEVEL2_DISCARD_ACTIVE_PDU =
|
||||
MWI_PDU_PREFIX +
|
||||
MWI_LEVEL2_PDU_ADDRESS +
|
||||
MWI_PID_DEFAULT +
|
||||
MWI_DCS_DISCARD_ACTIVE +
|
||||
MWI_TIMESTAMP +
|
||||
MWI_UD_DEFAULT;
|
||||
|
||||
function testLevel2DiscardActive() {
|
||||
|
||||
function onLevel2Active(event) {
|
||||
let status = event.status;
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, true);
|
||||
is(status.messageCount, -1);
|
||||
is(status.returnNumber, MWI_LEVEL2_SENDER);
|
||||
is(status.returnMessage, MWI_DEFAULT_BODY);
|
||||
isVoicemailStatus(status);
|
||||
}
|
||||
|
||||
sendIndicatorPDU(MWI_LEVEL2_DISCARD_ACTIVE_PDU,
|
||||
onLevel2Active,
|
||||
testLevel2DiscardInactive);
|
||||
function testLevel2DiscardActive(aActive) {
|
||||
log(" Active: " + aActive);
|
||||
|
||||
let sender = "+15125551235";
|
||||
let body = "1 new voicemail";
|
||||
let pdu = PDUBuilder.buildLevel2DiscardMwi(aActive, sender, body);
|
||||
return sendIndicatorPDUAndWait(pdu)
|
||||
.then((aResults) => checkEventStatus(aResults[0], 0, aActive,
|
||||
(aActive ? -1 : 0), sender, body));
|
||||
}
|
||||
|
||||
const MWI_LEVEL2_DISCARD_INACTIVE_PDU =
|
||||
MWI_PDU_PREFIX +
|
||||
MWI_LEVEL2_PDU_ADDRESS +
|
||||
MWI_PID_DEFAULT +
|
||||
MWI_DCS_DISCARD_INACTIVE +
|
||||
MWI_TIMESTAMP +
|
||||
MWI_UD_DEFAULT;
|
||||
|
||||
function testLevel2DiscardInactive() {
|
||||
function onLevel2Inactive(event) {
|
||||
let status = event.status;
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, false);
|
||||
is(status.messageCount, 0);
|
||||
is(status.returnNumber, MWI_LEVEL2_SENDER);
|
||||
is(status.returnMessage, MWI_DEFAULT_BODY);
|
||||
isVoicemailStatus(status);
|
||||
}
|
||||
|
||||
sendIndicatorPDU(MWI_LEVEL2_DISCARD_INACTIVE_PDU,
|
||||
onLevel2Inactive,
|
||||
testLevel3DiscardActive);
|
||||
}
|
||||
|
||||
|
||||
// Tests for Level 3 MWI with a message count in the User Data Header
|
||||
const MWI_LEVEL3_SENDER = "+15125551236";
|
||||
const MWI_LEVEL3_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL3_SENDER);
|
||||
function testLevel3DiscardActive(aMessageCount) {
|
||||
log(" Message Count: " + aMessageCount);
|
||||
|
||||
const MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT = 3;
|
||||
const MWI_LEVEL3_ACTIVE_BODY = "3 new voicemails";
|
||||
const MWI_LEVEL3_ACTIVE_UD = PDUBuilder.buildUserData({
|
||||
headers: [{
|
||||
id: RIL.PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION,
|
||||
length: 2,
|
||||
octets: [
|
||||
RIL.PDU_MWI_STORE_TYPE_DISCARD,
|
||||
MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT
|
||||
]
|
||||
}],
|
||||
body: MWI_LEVEL3_ACTIVE_BODY
|
||||
let sender = "+15125551236";
|
||||
let body = aMessageCount + " voicemails";
|
||||
let pdu = PDUBuilder.buildLevel3DiscardMwi(aMessageCount, sender, body);
|
||||
return sendIndicatorPDUAndWait(pdu)
|
||||
.then((aResults) => checkEventStatus(aResults[0], 0, !!aMessageCount,
|
||||
aMessageCount, sender, body));
|
||||
}
|
||||
|
||||
startTestCommon(function() {
|
||||
return Promise.resolve()
|
||||
|
||||
.then(() => log("Testing Message Waiting Indication Group"))
|
||||
// Level 2 discarded active/inactive MWI.
|
||||
.then(() => log(" Discard Message"))
|
||||
.then(() => testLevel2DiscardActive(true))
|
||||
.then(() => testLevel2DiscardActive(false))
|
||||
|
||||
.then(() => log("Testing Special SMS Message Indication"))
|
||||
.then(() => log(" Discard Message"))
|
||||
// Level 3 discarded active/inactive MWI.
|
||||
.then(() => testLevel3DiscardActive(3))
|
||||
.then(() => testLevel3DiscardActive(0));
|
||||
});
|
||||
|
||||
const MWI_LEVEL3_DISCARD_ACTIVE_PDU =
|
||||
MWI_PDU_UDH_PREFIX +
|
||||
MWI_LEVEL3_PDU_ADDRESS +
|
||||
MWI_PID_DEFAULT +
|
||||
MWI_DCS_DISCARD_ACTIVE +
|
||||
MWI_TIMESTAMP +
|
||||
MWI_LEVEL3_ACTIVE_UD;
|
||||
|
||||
function testLevel3DiscardActive() {
|
||||
|
||||
function onLevel3Active(event) {
|
||||
let status = event.status;
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, true);
|
||||
is(status.messageCount, MWI_LEVEL3_ACTIVE_UDH_MSG_COUNT);
|
||||
is(status.returnNumber, MWI_LEVEL3_SENDER);
|
||||
is(status.returnMessage, MWI_LEVEL3_ACTIVE_BODY);
|
||||
isVoicemailStatus(status);
|
||||
}
|
||||
|
||||
sendIndicatorPDU(MWI_LEVEL3_DISCARD_ACTIVE_PDU,
|
||||
onLevel3Active,
|
||||
testLevel3DiscardInactive);
|
||||
}
|
||||
|
||||
const MWI_LEVEL3_INACTIVE_BODY = "No unread voicemails";
|
||||
const MWI_LEVEL3_INACTIVE_UD = PDUBuilder.buildUserData({
|
||||
headers: [{
|
||||
id: RIL.PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION,
|
||||
length: 2,
|
||||
octets: [
|
||||
RIL.PDU_MWI_STORE_TYPE_DISCARD,
|
||||
0 // messageCount
|
||||
]
|
||||
}],
|
||||
body: MWI_LEVEL3_INACTIVE_BODY
|
||||
});
|
||||
|
||||
const MWI_LEVEL3_DISCARD_INACTIVE_PDU =
|
||||
MWI_PDU_UDH_PREFIX +
|
||||
MWI_LEVEL3_PDU_ADDRESS +
|
||||
MWI_PID_DEFAULT +
|
||||
MWI_DCS_DISCARD_ACTIVE +
|
||||
MWI_TIMESTAMP +
|
||||
MWI_LEVEL3_INACTIVE_UD;
|
||||
|
||||
function testLevel3DiscardInactive() {
|
||||
function onLevel3Inactive(event) {
|
||||
let status = event.status;
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, false);
|
||||
is(status.messageCount, 0);
|
||||
is(status.returnNumber, MWI_LEVEL3_SENDER);
|
||||
is(status.returnMessage, MWI_LEVEL3_INACTIVE_BODY);
|
||||
isVoicemailStatus(status);
|
||||
}
|
||||
|
||||
sendIndicatorPDU(MWI_LEVEL3_DISCARD_INACTIVE_PDU, onLevel3Inactive, cleanUp);
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
SpecialPowers.removePermission("voicemail", document);
|
||||
finish();
|
||||
}
|
||||
|
||||
testLevel2DiscardActive();
|
||||
|
@ -1,14 +0,0 @@
|
||||
from marionette_test import MarionetteTestCase
|
||||
import os
|
||||
|
||||
class TestVoicemailStatusChanged(MarionetteTestCase):
|
||||
|
||||
def testStatusChanged(self):
|
||||
this_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
pdu_builder_path = os.path.join(this_dir, "pdu_builder.js")
|
||||
self.marionette.import_script(pdu_builder_path)
|
||||
|
||||
test_path = os.path.join(this_dir, "test_voicemail_statuschanged.js")
|
||||
test = open(test_path, "r").read()
|
||||
self.marionette.set_script_timeout(30000)
|
||||
self.marionette.execute_async_script(test)
|
@ -298,6 +298,10 @@ interface CameraControl : MediaStream
|
||||
[Pref="camera.control.autofocus_moving_callback.enabled"]
|
||||
attribute CameraAutoFocusMovingCallback? onAutoFocusMoving;
|
||||
|
||||
/* this function is called whenever auto focus completes, due to continuous
|
||||
autofocus or a solicited auto focus. */
|
||||
attribute CameraAutoFocusCallback? onAutoFocusCompleted;
|
||||
|
||||
/* capture an image and return it as a blob to the 'onSuccess' callback;
|
||||
if the camera supports it, this may be invoked while the camera is
|
||||
already recording video.
|
||||
|
@ -4,9 +4,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
[JSImplementation="@mozilla.org/voicemailstatus;1",
|
||||
Pref="dom.voicemail.enabled"]
|
||||
|
||||
[Pref="dom.voicemail.enabled"]
|
||||
interface MozVoicemailStatus
|
||||
{
|
||||
readonly attribute unsigned long serviceId;
|
||||
|
@ -275,6 +275,8 @@ WEBIDL_FILES = [
|
||||
'MozSelfSupport.webidl',
|
||||
'MozTetheringManager.webidl',
|
||||
'MozTimeManager.webidl',
|
||||
'MozVoicemail.webidl',
|
||||
'MozVoicemailStatus.webidl',
|
||||
'MozWakeLock.webidl',
|
||||
'MutationEvent.webidl',
|
||||
'MutationObserver.webidl',
|
||||
@ -605,8 +607,6 @@ if CONFIG['MOZ_B2G_RIL']:
|
||||
'MozCellBroadcast.webidl',
|
||||
'MozIcc.webidl',
|
||||
'MozIccManager.webidl',
|
||||
'MozVoicemail.webidl',
|
||||
'MozVoicemailStatus.webidl'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_NFC']:
|
||||
@ -672,6 +672,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'MozSettingsTransactionEvent.webidl',
|
||||
'MozSmsEvent.webidl',
|
||||
'MozStkCommandEvent.webidl',
|
||||
'MozVoicemailEvent.webidl',
|
||||
'PageTransitionEvent.webidl',
|
||||
'PopStateEvent.webidl',
|
||||
'PopupBlockedEvent.webidl',
|
||||
@ -725,7 +726,6 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||
'MozCellBroadcastEvent.webidl',
|
||||
'MozVoicemailEvent.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
|
@ -234,6 +234,7 @@ static void Shutdown();
|
||||
#include "StreamingProtocolService.h"
|
||||
|
||||
#include "nsITelephonyService.h"
|
||||
#include "nsIVoicemailService.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
@ -352,6 +353,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileConnectionService,
|
||||
NS_CreateMobileConnectionService)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService,
|
||||
NS_CreateTelephonyService)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIVoicemailService,
|
||||
NS_CreateVoicemailService)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -790,6 +793,7 @@ NS_DEFINE_NAMED_CID(NS_SYNTHVOICEREGISTRY_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(TELEPHONY_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_VOICEMAIL_SERVICE_CID);
|
||||
|
||||
NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID);
|
||||
|
||||
@ -1079,6 +1083,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
#endif
|
||||
{ &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor },
|
||||
{ &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor },
|
||||
{ &kNS_VOICEMAIL_SERVICE_CID, false, nullptr, nsIVoicemailServiceConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
@ -1237,6 +1242,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ TELEPHONY_SERVICE_CONTRACTID, &kTELEPHONY_SERVICE_CID },
|
||||
{ "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID },
|
||||
{ NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID },
|
||||
{ NS_VOICEMAIL_SERVICE_CONTRACTID, &kNS_VOICEMAIL_SERVICE_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
@ -1181,8 +1181,6 @@ public abstract class GeckoApp
|
||||
GeckoAppShell.setContextGetter(this);
|
||||
GeckoAppShell.setGeckoInterface(this);
|
||||
|
||||
ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
|
||||
|
||||
Tabs.getInstance().attachToContext(this);
|
||||
try {
|
||||
Favicons.initializeWithContext(this);
|
||||
|
@ -166,7 +166,6 @@ public class GeckoView extends LayerView
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(mNativeEventListener,
|
||||
"Accessibility:Ready");
|
||||
|
||||
ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
|
||||
initializeView(EventDispatcher.getInstance());
|
||||
|
||||
if (GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching, GeckoThread.LaunchState.Launched)) {
|
||||
|
@ -10,6 +10,7 @@ import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.MessageQueue;
|
||||
import android.util.Log;
|
||||
|
||||
@ -25,10 +26,10 @@ public final class ThreadUtils {
|
||||
THROW,
|
||||
}
|
||||
|
||||
private static volatile Thread sUiThread;
|
||||
private static volatile Thread sBackgroundThread;
|
||||
private static final Thread sUiThread = Looper.getMainLooper().getThread();
|
||||
private static final Handler sUiHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private static Handler sUiHandler;
|
||||
private static volatile Thread sBackgroundThread;
|
||||
|
||||
// Referenced directly from GeckoAppShell in highly performance-sensitive code (The extra
|
||||
// function call of the getter was harming performance. (Bug 897123))
|
||||
@ -79,11 +80,6 @@ public final class ThreadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setUiThread(Thread thread, Handler handler) {
|
||||
sUiThread = thread;
|
||||
sUiHandler = handler;
|
||||
}
|
||||
|
||||
public static void setBackgroundThread(Thread thread) {
|
||||
sBackgroundThread = thread;
|
||||
}
|
||||
|
@ -1574,7 +1574,10 @@ SpecialPowersAPI.prototype = {
|
||||
|
||||
var xferable = Components.classes["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Components.interfaces.nsITransferable);
|
||||
xferable.init(this._getDocShell(content.window)
|
||||
// in e10s b-c tests |content.window| is null whereas |window| works fine.
|
||||
// for some non-e10s mochi tests, |window| is null whereas |content.window|
|
||||
// works fine. So we take whatever is non-null!
|
||||
xferable.init(this._getDocShell(content.window || window)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext));
|
||||
xferable.addDataFlavor(flavor);
|
||||
this._cb.getData(xferable, whichClipboard);
|
||||
|
@ -1,5 +1,4 @@
|
||||
[DEFAULT]
|
||||
skip-if = e10s
|
||||
|
||||
[browser_passwordmgr_fields.js]
|
||||
[browser_passwordmgr_observers.js]
|
||||
|
@ -25,6 +25,16 @@ const SearchAutocompleteProviderInternal = {
|
||||
*/
|
||||
priorityMatches: null,
|
||||
|
||||
/**
|
||||
* Array of objects in the format returned by findMatchByAlias.
|
||||
*/
|
||||
aliasMatches: null,
|
||||
|
||||
/**
|
||||
* Object for the default search match.
|
||||
**/
|
||||
defaultMatch: null,
|
||||
|
||||
initialize: function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
Services.search.init(status => {
|
||||
@ -60,6 +70,17 @@ const SearchAutocompleteProviderInternal = {
|
||||
|
||||
_refresh: function () {
|
||||
this.priorityMatches = [];
|
||||
this.aliasMatches = [];
|
||||
this.defaultMatch = null;
|
||||
|
||||
let currentEngine = Services.search.currentEngine;
|
||||
// This can be null in XCPShell.
|
||||
if (currentEngine) {
|
||||
this.defaultMatch = {
|
||||
engineName: currentEngine.name,
|
||||
iconUrl: currentEngine.iconURI ? currentEngine.iconURI.spec : null,
|
||||
}
|
||||
}
|
||||
|
||||
// The search engines will always be processed in the order returned by the
|
||||
// search service, which can be defined by the user.
|
||||
@ -67,19 +88,25 @@ const SearchAutocompleteProviderInternal = {
|
||||
},
|
||||
|
||||
_addEngine: function (engine) {
|
||||
let token = engine.getResultDomain();
|
||||
if (!token) {
|
||||
return;
|
||||
if (engine.alias) {
|
||||
this.aliasMatches.push({
|
||||
alias: engine.alias,
|
||||
engineName: engine.name,
|
||||
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
|
||||
});
|
||||
}
|
||||
|
||||
this.priorityMatches.push({
|
||||
token: token,
|
||||
// The searchForm property returns a simple URL for the search engine, but
|
||||
// we may need an URL which includes an affiliate code (bug 990799).
|
||||
url: engine.searchForm,
|
||||
engineName: engine.name,
|
||||
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
|
||||
});
|
||||
let domain = engine.getResultDomain();
|
||||
if (domain) {
|
||||
this.priorityMatches.push({
|
||||
token: domain,
|
||||
// The searchForm property returns a simple URL for the search engine, but
|
||||
// we may need an URL which includes an affiliate code (bug 990799).
|
||||
url: engine.searchForm,
|
||||
engineName: engine.name,
|
||||
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
@ -123,7 +150,36 @@ this.PlacesSearchAutocompleteProvider = Object.freeze({
|
||||
// Match at the beginning for now. In the future, an "options" argument may
|
||||
// allow the matching behavior to be tuned.
|
||||
return SearchAutocompleteProviderInternal.priorityMatches
|
||||
.find(m => m.token.startsWith(searchToken));
|
||||
.find(m => m.token.startsWith(searchToken));
|
||||
}),
|
||||
|
||||
/**
|
||||
* Matches a given search string to an item that should be included by
|
||||
* components wishing to search using search engine aliases, like
|
||||
* autocomple.
|
||||
*
|
||||
* @param searchToken
|
||||
* Search string to match exactly a search engine alias.
|
||||
*
|
||||
* @return An object with the following properties, or undefined if the token
|
||||
* does not match any relevant URL:
|
||||
* {
|
||||
* alias: The matched search engine's alias.
|
||||
* engineName: The display name of the search engine.
|
||||
* iconUrl: Icon associated to the match, or null if not available.
|
||||
* }
|
||||
*/
|
||||
findMatchByAlias: Task.async(function* (searchToken) {
|
||||
yield this.ensureInitialized();
|
||||
|
||||
return SearchAutocompleteProviderInternal.aliasMatches
|
||||
.find(m => m.alias == searchToken);
|
||||
}),
|
||||
|
||||
getDefaultMatch: Task.async(function* () {
|
||||
yield this.ensureInitialized();
|
||||
|
||||
return SearchAutocompleteProviderInternal.defaultMatch;
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -706,6 +706,12 @@ Search.prototype = {
|
||||
hasFirstResult = true;
|
||||
}
|
||||
|
||||
if (this._enableActions && !hasFirstResult) {
|
||||
// If it's not a bookmarked keyword, then it may be a search engine
|
||||
// with an alias - which works like a keyword.
|
||||
hasFirstResult = yield this._matchSearchEngineAlias();
|
||||
}
|
||||
|
||||
let shouldAutofill = this._shouldAutofill;
|
||||
if (this.pending && !hasFirstResult && shouldAutofill) {
|
||||
// Or it may look like a URL we know about from search engines.
|
||||
@ -717,6 +723,11 @@ Search.prototype = {
|
||||
hasFirstResult = yield this._matchKnownUrl(conn, queries);
|
||||
}
|
||||
|
||||
if (this.pending && this._enableActions && !hasFirstResult) {
|
||||
// When all else fails, we search using the current search engine.
|
||||
yield this._matchCurrentSearchEngine();
|
||||
}
|
||||
|
||||
yield this._sleep(Prefs.delay);
|
||||
if (!this.pending)
|
||||
return;
|
||||
@ -828,6 +839,48 @@ Search.prototype = {
|
||||
return true;
|
||||
},
|
||||
|
||||
_matchSearchEngineAlias: function* () {
|
||||
if (this._searchTokens.length < 2)
|
||||
return false;
|
||||
|
||||
let match = yield PlacesSearchAutocompleteProvider.findMatchByAlias(
|
||||
this._searchTokens[0]);
|
||||
if (!match)
|
||||
return false;
|
||||
|
||||
let query = this._searchTokens.slice(1).join(" ");
|
||||
|
||||
yield this._addSearchEngineMatch(match, query);
|
||||
return true;
|
||||
},
|
||||
|
||||
_matchCurrentSearchEngine: function* () {
|
||||
let match = yield PlacesSearchAutocompleteProvider.getDefaultMatch();
|
||||
if (!match)
|
||||
return;
|
||||
|
||||
let query = this._originalSearchString;
|
||||
|
||||
yield this._addSearchEngineMatch(match, query);
|
||||
},
|
||||
|
||||
_addSearchEngineMatch: function* (match, query) {
|
||||
let value = makeActionURL("searchengine", {
|
||||
engineName: match.engineName,
|
||||
input: this._originalSearchString,
|
||||
searchQuery: query,
|
||||
});
|
||||
|
||||
this._addMatch({
|
||||
value: value,
|
||||
comment: match.engineName,
|
||||
icon: match.iconUrl,
|
||||
style: "action searchengine",
|
||||
finalCompleteValue: this._trimmedOriginalSearchString,
|
||||
frecency: FRECENCY_SEARCHENGINES_DEFAULT,
|
||||
});
|
||||
},
|
||||
|
||||
_onResultRow: function (row) {
|
||||
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT);
|
||||
let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE);
|
||||
|
@ -0,0 +1,33 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
add_task(function*() {
|
||||
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
|
||||
"http://s.example.com/search");
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
Services.search.currentEngine = engine;
|
||||
Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "",
|
||||
"GET", "http://s.example.com/search");
|
||||
|
||||
|
||||
yield check_autocomplete({
|
||||
search: "doit",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "doit", searchQuery: "doit"}), title: "MozSearch" }, ]
|
||||
});
|
||||
|
||||
yield check_autocomplete({
|
||||
search: "doit mozilla",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "AliasedMozSearch", input: "doit mozilla", searchQuery: "mozilla"}), title: "AliasedMozSearch" }, ]
|
||||
});
|
||||
|
||||
yield check_autocomplete({
|
||||
search: "doit mozzarella mozilla",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "AliasedMozSearch", input: "doit mozzarella mozilla", searchQuery: "mozzarella mozilla"}), title: "AliasedMozSearch" }, ]
|
||||
});
|
||||
|
||||
yield cleanup();
|
||||
});
|
@ -0,0 +1,35 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
add_task(function*() {
|
||||
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
|
||||
"http://s.example.com/search");
|
||||
let engine = Services.search.getEngineByName("MozSearch");
|
||||
Services.search.currentEngine = engine;
|
||||
Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "",
|
||||
"GET", "http://s.example.com/search");
|
||||
|
||||
do_log_info("search engine");
|
||||
yield check_autocomplete({
|
||||
search: "mozilla",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozilla", searchQuery: "mozilla"}), title: "MozSearch" }, ]
|
||||
});
|
||||
|
||||
do_log_info("search engine, uri-like input");
|
||||
yield check_autocomplete({
|
||||
search: "http:///",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "http:///", searchQuery: "http:///"}), title: "MozSearch" }, ]
|
||||
});
|
||||
|
||||
do_log_info("search engine, multiple words");
|
||||
yield check_autocomplete({
|
||||
search: "mozzarella cheese",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozzarella cheese", searchQuery: "mozzarella cheese"}), title: "MozSearch" }, ]
|
||||
});
|
||||
|
||||
yield cleanup();
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user