mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 22:37:50 +00:00
Merge m-c to inbound. a=merge
This commit is contained in:
commit
67ab30de60
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -19,8 +19,8 @@
|
||||
<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="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
|
@ -17,8 +17,8 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -19,8 +19,8 @@
|
||||
<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="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "477b5672811ed970a7476fe6f67dba546a302dce",
|
||||
"git_revision": "45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "5bab67b888d1491d1718cf1a7349bcef3114cbab",
|
||||
"revision": "936633804b786ab99d2afc97311dc5cedeade648",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -284,6 +284,7 @@
|
||||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
@ -636,22 +636,6 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
||||
background-image: -moz-element(#historySwipeAnimationNextPageSnapshot);
|
||||
}
|
||||
|
||||
/* Identity UI */
|
||||
#identity-popup-content-box:not(.chromeUI) > #identity-popup-brandName,
|
||||
#identity-popup-content-box:not(.chromeUI) > #identity-popup-chromeLabel,
|
||||
#identity-popup-content-box.chromeUI > .identity-popup-label:not(#identity-popup-brandName):not(#identity-popup-chromeLabel),
|
||||
#identity-popup-content-box.chromeUI > .identity-popup-description,
|
||||
#identity-popup.chromeUI > #identity-popup-button-container,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-content-host ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-content-owner ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-connectedToLabel2 ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-runByLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Full Screen UI */
|
||||
|
||||
#fullscr-toggler {
|
||||
|
@ -6685,14 +6685,6 @@ var gIdentityHandler = {
|
||||
this._permissionList = document.getElementById("identity-popup-permission-list");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for commands on the help button in the "identity-popup" panel.
|
||||
*/
|
||||
handleHelpCommand : function(event) {
|
||||
openHelpLink("secure-connection");
|
||||
this._identityPopup.hidePopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for mouseclicks on the "More Information" button in the
|
||||
* "identity-popup" panel.
|
||||
@ -7051,8 +7043,6 @@ var gIdentityHandler = {
|
||||
},
|
||||
|
||||
onPopupShown : function(event) {
|
||||
document.getElementById('identity-popup-more-info-button').focus();
|
||||
|
||||
this._identityPopup.addEventListener("blur", this, true);
|
||||
this._identityPopup.addEventListener("popuphidden", this);
|
||||
},
|
||||
|
@ -9,6 +9,7 @@
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/browser-lightweightTheme.css" type="text/css"?>
|
||||
@ -406,67 +407,6 @@
|
||||
|
||||
<menupopup id="placesContext"/>
|
||||
|
||||
<!-- Popup for site identity information -->
|
||||
<panel id="identity-popup"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
noautofocus="true"
|
||||
onpopupshown="if (event.target == this)
|
||||
gIdentityHandler.onPopupShown(event);"
|
||||
orient="vertical"
|
||||
level="top">
|
||||
<hbox id="identity-popup-container" align="top">
|
||||
<image id="identity-popup-icon"/>
|
||||
<vbox id="identity-popup-content-box">
|
||||
<label id="identity-popup-brandName"
|
||||
class="identity-popup-label"
|
||||
value="&brandFullName;"/>
|
||||
<label id="identity-popup-chromeLabel"
|
||||
class="identity-popup-label"/>
|
||||
<label id="identity-popup-connectedToLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.connectedTo;"/>
|
||||
<label id="identity-popup-connectedToLabel2"
|
||||
class="identity-popup-label"
|
||||
value="&identity.unverifiedsite2;"/>
|
||||
<description id="identity-popup-content-host"
|
||||
class="identity-popup-description"/>
|
||||
<label id="identity-popup-runByLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.runBy;"/>
|
||||
<description id="identity-popup-content-owner"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-supplemental"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-verifier"
|
||||
class="identity-popup-description"/>
|
||||
<hbox id="identity-popup-encryption" flex="1">
|
||||
<vbox>
|
||||
<image id="identity-popup-encryption-icon"/>
|
||||
</vbox>
|
||||
<description id="identity-popup-encryption-label" flex="1"
|
||||
class="identity-popup-description"/>
|
||||
</hbox>
|
||||
<vbox id="identity-popup-permissions">
|
||||
<separator class="thin"/>
|
||||
<label class="identity-popup-label header"
|
||||
value="&identity.permissions;"/>
|
||||
<vbox id="identity-popup-permission-list" class="indent"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<!-- Footer button to open security page info -->
|
||||
<hbox id="identity-popup-button-container" align="center">
|
||||
<button id="identity-popup-help-icon"
|
||||
oncommand="gIdentityHandler.handleHelpCommand(event);"
|
||||
tooltiptext="&identity.help.tooltip;"/>
|
||||
<spacer flex="1"/>
|
||||
<button id="identity-popup-more-info-button"
|
||||
label="&identity.moreInfoLinkText;"
|
||||
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top">
|
||||
<hbox>
|
||||
<button class="ctrlTab-preview" flex="1"/>
|
||||
@ -549,6 +489,7 @@
|
||||
#include popup-notifications.inc
|
||||
|
||||
#include ../../components/customizableui/content/panelUI.inc.xul
|
||||
#include ../../components/controlcenter/content/panel.inc.xul
|
||||
|
||||
<hbox id="downloads-animation-container" mousethrough="always">
|
||||
<vbox id="downloads-notification-anchor">
|
||||
|
59
browser/components/controlcenter/content/panel.inc.xul
Normal file
59
browser/components/controlcenter/content/panel.inc.xul
Normal file
@ -0,0 +1,59 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<panel id="identity-popup"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
noautofocus="true"
|
||||
onpopupshown="if (event.target == this)
|
||||
gIdentityHandler.onPopupShown(event);"
|
||||
orient="vertical"
|
||||
level="top">
|
||||
<hbox id="identity-popup-container" align="top">
|
||||
<image id="identity-popup-icon"/>
|
||||
<vbox id="identity-popup-content-box">
|
||||
<label id="identity-popup-brandName"
|
||||
class="identity-popup-label"
|
||||
value="&brandFullName;"/>
|
||||
<label id="identity-popup-chromeLabel"
|
||||
class="identity-popup-label"/>
|
||||
<label id="identity-popup-connectedToLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.connectedTo;"/>
|
||||
<label id="identity-popup-connectedToLabel2"
|
||||
class="identity-popup-label"
|
||||
value="&identity.unverifiedsite2;"/>
|
||||
<description id="identity-popup-content-host"
|
||||
class="identity-popup-description"/>
|
||||
<label id="identity-popup-runByLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.runBy;"/>
|
||||
<description id="identity-popup-content-owner"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-supplemental"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-verifier"
|
||||
class="identity-popup-description"/>
|
||||
<hbox id="identity-popup-encryption" flex="1">
|
||||
<vbox>
|
||||
<image id="identity-popup-encryption-icon"/>
|
||||
</vbox>
|
||||
<description id="identity-popup-encryption-label" flex="1"
|
||||
class="identity-popup-description"/>
|
||||
</hbox>
|
||||
<vbox id="identity-popup-permissions">
|
||||
<separator class="thin"/>
|
||||
<label class="identity-popup-label header"
|
||||
value="&identity.permissions;"/>
|
||||
<vbox id="identity-popup-permission-list" class="indent"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<!-- Footer button to open security page info -->
|
||||
<hbox id="identity-popup-button-container" align="center">
|
||||
<button id="identity-popup-more-info-button" flex="1"
|
||||
label="&identity.moreInfoLinkText2;"
|
||||
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
|
||||
</hbox>
|
||||
</panel>
|
@ -54,3 +54,6 @@ if CONFIG['MOZ_SAFE_BROWSING']:
|
||||
|
||||
with Files('safebrowsing/*'):
|
||||
BUG_COMPONENT = ('Toolkit', 'Phishing Protection')
|
||||
|
||||
with Files('controlcenter/**'):
|
||||
BUG_COMPONENT = ('Firefox', 'General')
|
||||
|
@ -12,6 +12,7 @@ support-files =
|
||||
helper_disable_cache.js
|
||||
doc_theme.css
|
||||
doc_viewsource.html
|
||||
browser_toolbox_options_enable_serviceworkers_testing_frame_script.js
|
||||
browser_toolbox_options_enable_serviceworkers_testing.html
|
||||
serviceworker.js
|
||||
|
||||
@ -66,7 +67,6 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
|
||||
[browser_toolbox_custom_host.js]
|
||||
[browser_toolbox_theme_registration.js]
|
||||
[browser_toolbox_options_enable_serviceworkers_testing.js]
|
||||
skip-if = true # Bug 1153407 - this test breaks subsequent tests and is not e10s compatible
|
||||
[browser_toolbox_selected_tool_unavailable.js]
|
||||
|
||||
# We want this test to run for mochitest-dt as well, so we include it here:
|
||||
|
@ -3,56 +3,8 @@
|
||||
<head>
|
||||
<title>browser_toolbox_options_enable_serviceworkers_testing.html</title>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
div {
|
||||
width: 260px;
|
||||
height: 24px;
|
||||
border: 1px solid #000;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 20px
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
function log(msg) {
|
||||
var output = document.getElementById("output");
|
||||
|
||||
output.innerHTML = msg;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("serviceworker.js").then(
|
||||
swr => {
|
||||
var msg = "";
|
||||
var button = document.getElementById("button");
|
||||
if (swr.installing) {
|
||||
msg += "Installing worker/";
|
||||
}
|
||||
if (swr.waiting) {
|
||||
msg += "Waiting worker/";
|
||||
}
|
||||
if (swr.active) {
|
||||
msg += "Active worker/";
|
||||
}
|
||||
log(msg);
|
||||
button.click();
|
||||
},
|
||||
error => {
|
||||
var button = document.getElementById("button");
|
||||
if (error.name === "SecurityError") {
|
||||
log("SecurityError");
|
||||
}
|
||||
button.click();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test in page</h1>
|
||||
<input id="button"
|
||||
type="button"
|
||||
value="Worker clicks here"/>
|
||||
<br>
|
||||
<div id="output">No output</div>
|
||||
<h1>SW-test</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,13 +4,19 @@
|
||||
// Test that enabling Service Workers testing option enables the
|
||||
// mServiceWorkersTestingEnabled attribute added to nsPIDOMWindow.
|
||||
|
||||
const COMMON_FRAME_SCRIPT_URL =
|
||||
"chrome://browser/content/devtools/frame-script-utils.js";
|
||||
const ROOT_TEST_DIR =
|
||||
getRootDirectory(gTestPath);
|
||||
const FRAME_SCRIPT_URL =
|
||||
ROOT_TEST_DIR +
|
||||
"browser_toolbox_options_enable_serviceworkers_testing_frame_script.js";
|
||||
const TEST_URI = URL_ROOT +
|
||||
"browser_toolbox_options_enable_serviceworkers_testing.html";
|
||||
|
||||
const ELEMENT_ID = "devtools-enable-serviceWorkersTesting";
|
||||
|
||||
let toolbox;
|
||||
let doc;
|
||||
|
||||
function test() {
|
||||
// Note: Pref dom.serviceWorkers.testing.enabled is false since we are testing
|
||||
@ -19,16 +25,19 @@ function test() {
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", false]
|
||||
]}, start);
|
||||
]}, init);
|
||||
}
|
||||
|
||||
function start() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
function init() {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.messageManager.loadFrameScript(COMMON_FRAME_SCRIPT_URL, false);
|
||||
linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
gDevTools.showToolbox(target).then(testSelectTool);
|
||||
}, true);
|
||||
|
||||
@ -37,89 +46,24 @@ function start() {
|
||||
|
||||
function testSelectTool(aToolbox) {
|
||||
toolbox = aToolbox;
|
||||
toolbox.once("options-selected", () => {
|
||||
testRegisterFails().then(testRegisterInstallingWorker);
|
||||
});
|
||||
toolbox.once("options-selected", start);
|
||||
toolbox.selectTool("options");
|
||||
}
|
||||
|
||||
function testRegisterFails() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let output = doc.getElementById("output");
|
||||
let button = doc.getElementById("button");
|
||||
|
||||
function doTheCheck() {
|
||||
info("Testing it doesn't registers correctly until enable testing");
|
||||
is(output.textContent,
|
||||
"SecurityError",
|
||||
"SecurityError expected");
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
if (output.textContent !== "No output") {
|
||||
doTheCheck();
|
||||
}
|
||||
|
||||
button.addEventListener('click', function onClick() {
|
||||
button.removeEventListener('click', onClick);
|
||||
doTheCheck();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
function register() {
|
||||
return executeInContent("devtools:sw-test:register");
|
||||
}
|
||||
|
||||
function testRegisterInstallingWorker() {
|
||||
toggleServiceWorkersTestingCheckbox().then(() => {
|
||||
let output = doc.getElementById("output");
|
||||
let button = doc.getElementById("button");
|
||||
|
||||
function doTheCheck() {
|
||||
info("Testing it registers correctly and there is an installing worker");
|
||||
is(output.textContent,
|
||||
"Installing worker/",
|
||||
"Installing worker expected");
|
||||
testRegisterFailsWhenToolboxCloses();
|
||||
}
|
||||
|
||||
if (output.textContent !== "No output") {
|
||||
doTheCheck();
|
||||
}
|
||||
|
||||
button.addEventListener('click', function onClick() {
|
||||
button.removeEventListener('click', onClick);
|
||||
doTheCheck();
|
||||
});
|
||||
});
|
||||
function unregister(swr) {
|
||||
return executeInContent("devtools:sw-test:unregister");
|
||||
}
|
||||
|
||||
// Workers should be turned back off when we closes the toolbox
|
||||
function testRegisterFailsWhenToolboxCloses() {
|
||||
info("Testing it disable worker when closing the toolbox");
|
||||
toolbox.destroy()
|
||||
.then(reload)
|
||||
.then(testRegisterFails)
|
||||
.then(finishUp);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
let mm = getFrameScript();
|
||||
mm.sendAsyncMessage("devtools:test:reload");
|
||||
|
||||
return deferred.promise;
|
||||
function testRegisterFails(data) {
|
||||
is(data.success, false, "Register should fail with security error");
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
function toggleServiceWorkersTestingCheckbox() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let cbx = panel.panelDoc.getElementById(ELEMENT_ID);
|
||||
|
||||
@ -133,11 +77,46 @@ function toggleServiceWorkersTestingCheckbox() {
|
||||
|
||||
cbx.click();
|
||||
|
||||
return reload();
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
function reload() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
executeInContent("devtools:test:reload", {}, {}, false);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testRegisterSuccesses(data) {
|
||||
is(data.success, true, "Register should success");
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
function start() {
|
||||
register()
|
||||
.then(testRegisterFails)
|
||||
.then(toggleServiceWorkersTestingCheckbox)
|
||||
.then(reload)
|
||||
.then(register)
|
||||
.then(testRegisterSuccesses)
|
||||
.then(unregister)
|
||||
// Workers should be turned back off when we closes the toolbox
|
||||
.then(toolbox.destroy.bind(toolbox))
|
||||
.then(reload)
|
||||
.then(register)
|
||||
.then(testRegisterFails)
|
||||
.catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e);
|
||||
}).then(finishUp);
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
gBrowser.removeCurrentTab();
|
||||
toolbox = doc = null;
|
||||
toolbox = null;
|
||||
finish();
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// A helper frame-script for browser/devtools/framework service worker tests.
|
||||
|
||||
"use strict";
|
||||
|
||||
addMessageListener("devtools:sw-test:register", function(msg) {
|
||||
content.navigator.serviceWorker.register("serviceworker.js")
|
||||
.then(swr => {
|
||||
sendAsyncMessage("devtools:sw-test:register", {success: true});
|
||||
}, error => {
|
||||
sendAsyncMessage("devtools:sw-test:register", {success: false});
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener("devtools:sw-test:unregister", function(msg) {
|
||||
content.navigator.serviceWorker.getRegistration().then(swr => {
|
||||
swr.unregister().then(result => {
|
||||
sendAsyncMessage("devtools:sw-test:unregister",
|
||||
{success: result ? true : false});
|
||||
});
|
||||
});
|
||||
});
|
@ -65,3 +65,47 @@ function *openScratchpadWindow () {
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a content -> chrome message on the message manager (the window
|
||||
* messagemanager is used).
|
||||
* @param {String} name The message name
|
||||
* @return {Promise} A promise that resolves to the response data when the
|
||||
* message has been received
|
||||
*/
|
||||
function waitForContentMessage(name) {
|
||||
info("Expecting message " + name + " from content");
|
||||
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
let def = promise.defer();
|
||||
mm.addMessageListener(name, function onMessage(msg) {
|
||||
mm.removeMessageListener(name, onMessage);
|
||||
def.resolve(msg.data);
|
||||
});
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an async message to the frame script (chrome -> content) and wait for a
|
||||
* response message with the same name (content -> chrome).
|
||||
* @param {String} name The message name. Should be one of the messages defined
|
||||
* in doc_frame_script.js
|
||||
* @param {Object} data Optional data to send along
|
||||
* @param {Object} objects Optional CPOW objects to send along
|
||||
* @param {Boolean} expectResponse If set to false, don't wait for a response
|
||||
* with the same name from the content script. Defaults to true.
|
||||
* @return {Promise} Resolves to the response data if a response is expected,
|
||||
* immediately resolves otherwise
|
||||
*/
|
||||
function executeInContent(name, data={}, objects={}, expectResponse=true) {
|
||||
info("Sending message " + name + " to content");
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
mm.sendAsyncMessage(name, data, objects);
|
||||
if (expectResponse) {
|
||||
return waitForContentMessage(name);
|
||||
} else {
|
||||
return promise.resolve();
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,11 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Cu, Ci} = require("chrome");
|
||||
const {Cu, Ci} = require("chrome");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
const {Promise: promise} = require("resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
});
|
||||
|
||||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
|
||||
const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
|
||||
const MAX_LABEL_LENGTH = 40;
|
||||
@ -29,7 +23,7 @@ const LOW_PRIORITY_ELEMENTS = {
|
||||
"META": true,
|
||||
"SCRIPT": true,
|
||||
"STYLE": true,
|
||||
"TITLE": true,
|
||||
"TITLE": true
|
||||
};
|
||||
|
||||
/**
|
||||
@ -51,7 +45,6 @@ function HTMLBreadcrumbs(inspector) {
|
||||
this.selection = this.inspector.selection;
|
||||
this.chromeWin = this.inspector.panelWin;
|
||||
this.chromeDoc = this.inspector.panelDoc;
|
||||
this.DOMHelpers = new DOMHelpers(this.chromeWin);
|
||||
this._init();
|
||||
}
|
||||
|
||||
@ -93,10 +86,11 @@ HTMLBreadcrumbs.prototype = {
|
||||
this.container._scrollButtonDown.collapsed = true;
|
||||
|
||||
this.onscrollboxreflow = () => {
|
||||
if (this.container._scrollButtonDown.collapsed)
|
||||
if (this.container._scrollButtonDown.collapsed) {
|
||||
this.container.removeAttribute("overflows");
|
||||
else
|
||||
} else {
|
||||
this.container.setAttribute("overflows", true);
|
||||
}
|
||||
};
|
||||
|
||||
this.container.addEventListener("underflow", this.onscrollboxreflow, false);
|
||||
@ -118,12 +112,12 @@ HTMLBreadcrumbs.prototype = {
|
||||
*/
|
||||
selectionGuard: function() {
|
||||
let selection = this.selection.nodeFront;
|
||||
return (result) => {
|
||||
return result => {
|
||||
if (selection != this.selection.nodeFront) {
|
||||
return promise.reject("selection-changed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
@ -204,11 +198,6 @@ HTMLBreadcrumbs.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Until we have pseudoclass lock in the node.
|
||||
for (let pseudo of node.pseudoClassLocks) {
|
||||
|
||||
}
|
||||
|
||||
// Figure out which element (if any) needs ellipsing.
|
||||
// Substring for that element, then clear out any extras
|
||||
// (except for pseudo elements).
|
||||
@ -217,11 +206,11 @@ HTMLBreadcrumbs.prototype = {
|
||||
let maxClassLength = MAX_LABEL_LENGTH - tagText.length - idText.length;
|
||||
|
||||
if (tagText.length > maxTagLength) {
|
||||
tagText = tagText.substr(0, maxTagLength) + ELLIPSIS;
|
||||
idText = classesText = "";
|
||||
tagText = tagText.substr(0, maxTagLength) + ELLIPSIS;
|
||||
idText = classesText = "";
|
||||
} else if (idText.length > maxIdLength) {
|
||||
idText = idText.substr(0, maxIdLength) + ELLIPSIS;
|
||||
classesText = "";
|
||||
idText = idText.substr(0, maxIdLength) + ELLIPSIS;
|
||||
classesText = "";
|
||||
} else if (classesText.length > maxClassLength) {
|
||||
classesText = classesText.substr(0, maxClassLength) + ELLIPSIS;
|
||||
}
|
||||
@ -250,19 +239,20 @@ HTMLBreadcrumbs.prototype = {
|
||||
// for inspector.selection
|
||||
this.selection.setNodeFront(node, "breadcrumbs");
|
||||
|
||||
let title = this.chromeDoc.createElement("menuitem");
|
||||
title.setAttribute("label", this.inspector.strings.GetStringFromName("breadcrumbs.siblings"));
|
||||
title.setAttribute("disabled", "true");
|
||||
|
||||
let separator = this.chromeDoc.createElement("menuseparator");
|
||||
|
||||
let items = [title, separator];
|
||||
// Build a list of extra menu items that will be appended at the end of the
|
||||
// inspector node context menu.
|
||||
let items = [this.chromeDoc.createElement("menuseparator")];
|
||||
|
||||
this.walker.siblings(node, {
|
||||
whatToShow: Ci.nsIDOMNodeFilter.SHOW_ELEMENT
|
||||
}).then(siblings => {
|
||||
let nodes = siblings.nodes;
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
// Skip siblings of the documentElement node.
|
||||
if (nodes[i].nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let item = this.chromeDoc.createElement("menuitem");
|
||||
if (nodes[i] === node) {
|
||||
item.setAttribute("disabled", "true");
|
||||
@ -276,12 +266,14 @@ HTMLBreadcrumbs.prototype = {
|
||||
item.onmouseup = (function(node) {
|
||||
return function() {
|
||||
selection.setNodeFront(node, "breadcrumbs");
|
||||
}
|
||||
};
|
||||
})(nodes[i]);
|
||||
|
||||
items.push(item);
|
||||
this.inspector.showNodeMenu(button, "before_start", items);
|
||||
}
|
||||
|
||||
// Append the items to the inspector node context menu and show the menu.
|
||||
this.inspector.showNodeMenu(button, "before_start", items);
|
||||
});
|
||||
},
|
||||
|
||||
@ -445,8 +437,9 @@ HTMLBreadcrumbs.prototype = {
|
||||
}
|
||||
if (index > -1) {
|
||||
this.nodeHierarchy[index].button.setAttribute("checked", "true");
|
||||
if (this.hadFocus)
|
||||
if (this.hadFocus) {
|
||||
this.nodeHierarchy[index].button.focus();
|
||||
}
|
||||
}
|
||||
this.currentIndex = index;
|
||||
},
|
||||
@ -457,7 +450,6 @@ HTMLBreadcrumbs.prototype = {
|
||||
* @returns {Number} The index for this node or -1 if not found.
|
||||
*/
|
||||
indexOf: function(node) {
|
||||
let i = this.nodeHierarchy.length - 1;
|
||||
for (let i = this.nodeHierarchy.length - 1; i >= 0; i--) {
|
||||
if (this.nodeHierarchy[i].node === node) {
|
||||
return i;
|
||||
@ -492,9 +484,10 @@ HTMLBreadcrumbs.prototype = {
|
||||
|
||||
button.onkeypress = function onBreadcrumbsKeypress(e) {
|
||||
if (e.charCode == Ci.nsIDOMKeyEvent.DOM_VK_SPACE ||
|
||||
e.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN)
|
||||
e.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) {
|
||||
button.click();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
button.onBreadcrumbsClick = () => {
|
||||
this.selection.setNodeFront(node, "breadcrumbs");
|
||||
@ -574,9 +567,8 @@ HTMLBreadcrumbs.prototype = {
|
||||
if (response.hasLast) {
|
||||
deferred.resolve(fallback);
|
||||
return;
|
||||
} else {
|
||||
moreChildren();
|
||||
}
|
||||
moreChildren();
|
||||
}).then(null, this.selectionGuardEnd);
|
||||
};
|
||||
|
||||
@ -594,9 +586,8 @@ HTMLBreadcrumbs.prototype = {
|
||||
let idx = this.indexOf(node);
|
||||
if (idx > -1) {
|
||||
return idx;
|
||||
} else {
|
||||
node = node.parentNode();
|
||||
}
|
||||
node = node.parentNode();
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
@ -725,12 +716,14 @@ HTMLBreadcrumbs.prototype = {
|
||||
cmdDispatcher.focusedElement.parentNode == this.container);
|
||||
|
||||
if (!this.selection.isConnected()) {
|
||||
this.cutAfter(-1); // remove all the crumbs
|
||||
// remove all the crumbs
|
||||
this.cutAfter(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.selection.isElementNode()) {
|
||||
this.setCursor(-1); // no selection
|
||||
// no selection
|
||||
this.setCursor(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ support-files =
|
||||
|
||||
[browser_inspector_breadcrumbs.js]
|
||||
[browser_inspector_breadcrumbs_highlight_hover.js]
|
||||
[browser_inspector_breadcrumbs_menu.js]
|
||||
[browser_inspector_breadcrumbs_mutations.js]
|
||||
[browser_inspector_delete-selected-node-01.js]
|
||||
[browser_inspector_delete-selected-node-02.js]
|
||||
|
@ -0,0 +1,51 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the inspector node context menu appears when right-clicking on the
|
||||
// breadcrumbs nodes.
|
||||
|
||||
const TEST_URI = TEST_URL_ROOT + "doc_inspector_breadcrumbs.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URI);
|
||||
let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
|
||||
info("Select a test node and try to right-click on the selected breadcrumb");
|
||||
yield selectNode("#i1", inspector);
|
||||
let button = container.querySelector("button[checked]");
|
||||
|
||||
let onMenuShown = once(inspector.nodemenu, "popupshown");
|
||||
button.onclick({button: 2});
|
||||
yield onMenuShown;
|
||||
|
||||
ok(true, "The context menu appeared on right-click");
|
||||
|
||||
info("Right-click on a non selected crumb (the body node)");
|
||||
button = button.previousSibling;
|
||||
onMenuShown = once(inspector.nodemenu, "popupshown");
|
||||
let onInspectorUpdated = inspector.once("inspector-updated");
|
||||
button.onclick({button: 2});
|
||||
|
||||
yield onMenuShown;
|
||||
ok(true, "The context menu appeared on right-click");
|
||||
|
||||
yield onInspectorUpdated;
|
||||
is(inspector.selection.nodeFront.tagName.toLowerCase(), "body",
|
||||
"The body node was selected when right-clicking in the breadcrumbs");
|
||||
|
||||
info("Right-click on the html node");
|
||||
button = button.previousSibling;
|
||||
onMenuShown = once(inspector.nodemenu, "popupshown");
|
||||
onInspectorUpdated = inspector.once("inspector-updated");
|
||||
button.onclick({button: 2});
|
||||
|
||||
yield onMenuShown;
|
||||
ok(true, "The context menu appeared on right-click");
|
||||
|
||||
yield onInspectorUpdated;
|
||||
is(inspector.selection.nodeFront.tagName.toLowerCase(), "html",
|
||||
"The html node was selected when right-clicking in the breadcrumbs");
|
||||
});
|
@ -2,6 +2,7 @@
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
doc_force_gc.html
|
||||
doc_innerHTML.html
|
||||
doc_simple-test.html
|
||||
head.js
|
||||
@ -12,7 +13,6 @@ support-files =
|
||||
[browser_aaa-run-first-leaktest.js]
|
||||
[browser_marker-utils.js]
|
||||
[browser_markers-gc.js]
|
||||
skip-if = e10s # GC events seem unreliable in multiprocess
|
||||
[browser_markers-parse-html.js]
|
||||
[browser_markers-styles.js]
|
||||
[browser_markers-timestamp.js]
|
||||
|
@ -6,17 +6,16 @@
|
||||
*/
|
||||
|
||||
const TIME_CLOSE_TO = 10000;
|
||||
const TEST_URL = EXAMPLE_URL + "doc_force_gc.html"
|
||||
|
||||
function* spawnTest () {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
let { target, front } = yield initBackend(TEST_URL);
|
||||
let markers;
|
||||
|
||||
front.on("timeline-data", handler);
|
||||
let model = yield front.startRecording({ withTicks: true });
|
||||
|
||||
// Check async for markers found while GC/CCing between
|
||||
yield waitUntil(() => {
|
||||
forceCC();
|
||||
return !!markers;
|
||||
}, 100);
|
||||
|
||||
|
21
browser/devtools/performance/test/doc_force_gc.html
Normal file
21
browser/devtools/performance/test/doc_force_gc.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Performance tool + garbage collection test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
window.test = function () {
|
||||
SpecialPowers.Cu.forceGC();
|
||||
setTimeout(window.test, 100);
|
||||
};
|
||||
test();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -705,6 +705,10 @@ CSSCompleter.prototype = {
|
||||
// possibility of suggestions.
|
||||
switch(this.selectorState) {
|
||||
case SELECTOR_STATES.null:
|
||||
if (this.completing === ",") {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
query += "*";
|
||||
break;
|
||||
|
||||
|
@ -8,6 +8,8 @@ const {InspectorFront} = require("devtools/server/actors/inspector");
|
||||
const AUTOCOMPLETION_PREF = "devtools.editor.autocomplete";
|
||||
const TEST_URI = "data:text/html;charset=UTF-8,<html><body><bar></bar><div id='baz'></div><body></html>";
|
||||
|
||||
const wait = (delay) => new Promise(resolve => setTimeout(resolve, delay));
|
||||
|
||||
add_task(function*() {
|
||||
yield promiseTab(TEST_URI);
|
||||
yield runTests();
|
||||
@ -27,6 +29,7 @@ function* runTests() {
|
||||
yield testKeyboard(ed, edWin);
|
||||
yield testKeyboardCycle(ed, edWin);
|
||||
yield testKeyboardCycleForPrefixedString(ed, edWin);
|
||||
yield testKeyboardCSSComma(ed, edWin);
|
||||
teardown(ed, win);
|
||||
}
|
||||
|
||||
@ -87,6 +90,22 @@ function* testKeyboardCycleForPrefixedString(ed, win) {
|
||||
is (ed.getText(), "#baz", "Editor text has been updated");
|
||||
}
|
||||
|
||||
function* testKeyboardCSSComma(ed, win) {
|
||||
ed.focus();
|
||||
ed.setText("b");
|
||||
ed.setCursor({line: 1, ch: 1});
|
||||
|
||||
let isPopupOpened = false;
|
||||
let popupOpened = ed.getAutocompletionPopup().once("popup-opened");
|
||||
popupOpened.then(() => isPopupOpened = true);
|
||||
|
||||
EventUtils.synthesizeKey(",", { }, win);
|
||||
|
||||
yield wait(500);
|
||||
|
||||
ok(!isPopupOpened, "Autocompletion shouldn't be opened");
|
||||
}
|
||||
|
||||
function* testMouse(ed, win) {
|
||||
ed.focus();
|
||||
ed.setText("b");
|
||||
|
@ -286,6 +286,7 @@
|
||||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
@ -686,15 +686,10 @@ with that structure, consider a translation which ignores the preceding domain a
|
||||
just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
<!ENTITY identity.runBy "which is run by">
|
||||
|
||||
<!ENTITY identity.moreInfoLinkText "More Information…">
|
||||
<!ENTITY identity.moreInfoLinkText2 "More Information">
|
||||
|
||||
<!ENTITY identity.permissions "Permissions">
|
||||
|
||||
<!-- LOCALIZATION NOTE (identity.help.tooltip) : This string should be the
|
||||
localized title of this SUMO article
|
||||
https://support.mozilla.org/kb/how-do-i-tell-if-my-connection-is-secure -->
|
||||
<!ENTITY identity.help.tooltip "How do I tell if my connection to a website is secure?">
|
||||
|
||||
<!-- Name for the tabs toolbar as spoken by screen readers.
|
||||
The word "toolbar" is appended automatically and should not be contained below! -->
|
||||
<!ENTITY tabsToolbar.label "Browser tabs">
|
||||
|
@ -1025,105 +1025,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
/* Identity popup icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
/* Identity popup body text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-owner {
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -18px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure.png");
|
||||
}
|
||||
|
||||
#identity-popup-help-icon {
|
||||
-moz-appearance: none;
|
||||
margin-left: 0px;
|
||||
border: none;
|
||||
background: none;
|
||||
min-width: 0;
|
||||
list-style-image: url("moz-icon://stock/gtk-dialog-question?size=16");
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon:-moz-focusring {
|
||||
outline: 1px dotted;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
min-width: 280px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#identity-popup-button-container {
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
|
||||
padding: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
|
||||
.popup-notification-body[popupid="addon-progress"],
|
||||
|
74
browser/themes/linux/controlcenter/panel.css
Normal file
74
browser/themes/linux/controlcenter/panel.css
Normal file
@ -0,0 +1,74 @@
|
||||
/* 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 ../../shared/controlcenter/panel.inc.css
|
||||
|
||||
/* Identity popup icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
/* Identity popup body text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-owner {
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -18px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure.png");
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
min-width: 280px;
|
||||
padding: 10px;
|
||||
}
|
@ -134,6 +134,7 @@ browser.jar:
|
||||
skin/classic/browser/loop/menuPanel.png (loop/menuPanel.png)
|
||||
skin/classic/browser/loop/toolbar.png (loop/toolbar.png)
|
||||
skin/classic/browser/loop/toolbar-inverted.png (loop/toolbar-inverted.png)
|
||||
* skin/classic/browser/controlcenter/panel.css (controlcenter/panel.css)
|
||||
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
|
||||
skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png)
|
||||
skin/classic/browser/customizableui/customize-illustration-rtl.png (../shared/customizableui/customize-illustration-rtl.png)
|
||||
|
@ -3118,140 +3118,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
/* Popup Icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#identity-popup-icon {
|
||||
list-style-image: url("chrome://browser/skin/identity@2x.png");
|
||||
-moz-image-region: rect(0px, 128px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 128px, 256px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(256px, 128px, 384px, 0px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-owner {
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -24px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
margin-top: 5px;
|
||||
list-style-image: url("chrome://browser/skin/Secure-Glyph.png");
|
||||
}
|
||||
|
||||
#identity-popup-help-icon {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
margin: 10px 0 0 2px;
|
||||
background: none;
|
||||
min-width: 0;
|
||||
list-style-image: url("chrome://global/skin/icons/question-16.png");
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon:focus {
|
||||
@hudButtonFocused@
|
||||
}
|
||||
|
||||
#identity-popup-help-icon:hover:active {
|
||||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure-Glyph@2x.png");
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon {
|
||||
list-style-image: url("chrome://global/skin/icons/question-32.png");
|
||||
}
|
||||
}
|
||||
|
||||
#identity-popup {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#identity-popup-button-container {
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
border-top: 1px solid hsla(210,4%,10%,.12);
|
||||
padding: 16px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
|
||||
#notification-popup-box {
|
||||
@ -3431,21 +3297,6 @@ notification[value="loop-sharing-notification"] .messageImage {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Popup Buttons */
|
||||
#identity-popup-more-info-button {
|
||||
@hudButton@
|
||||
margin: 10px 0 0;
|
||||
min-height: 0px;
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button:focus {
|
||||
@hudButtonFocused@
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button:hover:active {
|
||||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
/* ::::: Keyboard UI Panel ::::: */
|
||||
|
||||
.KUI-panel {
|
||||
|
101
browser/themes/osx/controlcenter/panel.css
Normal file
101
browser/themes/osx/controlcenter/panel.css
Normal file
@ -0,0 +1,101 @@
|
||||
/* 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 ../../shared/controlcenter/panel.inc.css
|
||||
|
||||
/* Popup Icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#identity-popup-icon {
|
||||
list-style-image: url("chrome://browser/skin/identity@2x.png");
|
||||
-moz-image-region: rect(0px, 128px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 128px, 256px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(256px, 128px, 384px, 0px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-owner {
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-host ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -24px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
margin-top: 5px;
|
||||
list-style-image: url("chrome://browser/skin/Secure-Glyph.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure-Glyph@2x.png");
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
#identity-popup {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
padding: 16px;
|
||||
}
|
@ -192,6 +192,7 @@ browser.jar:
|
||||
skin/classic/browser/yosemite/loop/menuPanel@2x.png (loop/menuPanel-yosemite@2x.png)
|
||||
skin/classic/browser/yosemite/loop/toolbar.png (loop/toolbar-yosemite.png)
|
||||
skin/classic/browser/yosemite/loop/toolbar@2x.png (loop/toolbar-yosemite@2x.png)
|
||||
* skin/classic/browser/controlcenter/panel.css (controlcenter/panel.css)
|
||||
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
|
||||
skin/classic/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png)
|
||||
skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png (customizableui/customize-titleBar-toggle@2x.png)
|
||||
|
59
browser/themes/shared/controlcenter/panel.inc.css
Normal file
59
browser/themes/shared/controlcenter/panel.inc.css
Normal file
@ -0,0 +1,59 @@
|
||||
#identity-popup-content-box:not(.chromeUI) > #identity-popup-brandName,
|
||||
#identity-popup-content-box:not(.chromeUI) > #identity-popup-chromeLabel,
|
||||
#identity-popup-content-box.chromeUI > .identity-popup-label:not(#identity-popup-brandName):not(#identity-popup-chromeLabel),
|
||||
#identity-popup-content-box.chromeUI > .identity-popup-description,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-content-host ,
|
||||
#identity-popup-content-box.unknownIdentity > #identity-popup-content-owner ,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-connectedToLabel2 ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-connectedToLabel2 ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-runByLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
|
||||
list-style-image: url("chrome://branding/content/icon64.png");
|
||||
}
|
||||
|
||||
#identity-popup-brandName {
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
#identity-popup-content-box {
|
||||
max-width: 50ch;
|
||||
}
|
||||
|
||||
#identity-popup-button-container {
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button {
|
||||
border: none;
|
||||
border-top: 1px solid hsla(210,4%,10%,.14);
|
||||
background: transparent;
|
||||
-moz-appearance: none;
|
||||
margin-top: 5px;
|
||||
padding: 1.1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button:hover {
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button:hover:active {
|
||||
color: inherit;
|
||||
background-color: hsla(210,4%,10%,.12);
|
||||
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
|
||||
list-style-image: url("chrome://branding/content/icon128.png");
|
||||
-moz-image-region: rect(0, 128px, 128px, 0);
|
||||
}
|
||||
}
|
@ -91,21 +91,6 @@
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
#identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
|
||||
list-style-image: url("chrome://branding/content/icon64.png");
|
||||
}
|
||||
|
||||
#identity-popup-brandName {
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
#identity-popup-content-box {
|
||||
max-width: 50ch;
|
||||
}
|
||||
|
||||
@media not all and (min-resolution: 1.1dppx) {
|
||||
#page-proxy-favicon {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
@ -159,9 +144,4 @@
|
||||
#identity-box[open=true] > #page-proxy-favicon {
|
||||
-moz-image-region: rect(0, 96px, 32px, 64px);
|
||||
}
|
||||
|
||||
#identity-popup.chromeUI > #identity-popup-container > #identity-popup-icon {
|
||||
list-style-image: url("chrome://branding/content/icon128.png");
|
||||
-moz-image-region: rect(0, 128px, 128px, 0);
|
||||
}
|
||||
}
|
||||
|
@ -158,26 +158,33 @@
|
||||
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
|
||||
}
|
||||
|
||||
/* Vertical toolbar border */
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox:not(:-moz-lwtheme)::after,
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme),
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox:-moz-lwtheme,
|
||||
#main-window[customizing] #navigator-toolbox::after,
|
||||
#main-window[customizing] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
|
||||
border-left: 1px solid @toolbarShadowColor@;
|
||||
border-right: 1px solid @toolbarShadowColor@;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
#main-window[sizemode=normal] #browser-border-start,
|
||||
#main-window[sizemode=normal] #browser-border-end {
|
||||
display: -moz-box;
|
||||
background-color: @toolbarShadowColor@;
|
||||
width: 1px;
|
||||
}
|
||||
#main-window[sizemode=normal] #browser-bottombox {
|
||||
border: 1px solid @toolbarShadowColor@;
|
||||
border-top-style: none;
|
||||
background-clip: padding-box;
|
||||
/* Show borders on vista through win8, but not on win10 and later: */
|
||||
@media (-moz-os-version: windows-vista),
|
||||
(-moz-os-version: windows-win7),
|
||||
(-moz-os-version: windows-win8) {
|
||||
/* Vertical toolbar border */
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox:not(:-moz-lwtheme)::after,
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme),
|
||||
#main-window:not([customizing])[sizemode=normal] #navigator-toolbox:-moz-lwtheme,
|
||||
#main-window[customizing] #navigator-toolbox::after,
|
||||
#main-window[customizing] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
|
||||
border-left: 1px solid @toolbarShadowColor@;
|
||||
border-right: 1px solid @toolbarShadowColor@;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #browser-border-start,
|
||||
#main-window[sizemode=normal] #browser-border-end {
|
||||
display: -moz-box;
|
||||
background-color: @toolbarShadowColor@;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #browser-bottombox {
|
||||
border: 1px solid @toolbarShadowColor@;
|
||||
border-top-style: none;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #TabsToolbar {
|
||||
|
@ -2138,116 +2138,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
/* ::::: Identity Indicator Styling ::::: */
|
||||
|
||||
/* Popup Icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#identity-popup-content-host {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0 !important;
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.verifiedDomain > #identity-popup-content-owner {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -24px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure24.png");
|
||||
}
|
||||
|
||||
#identity-popup-help-icon {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
margin: 7px 0 0 -3px;
|
||||
background: none;
|
||||
min-width: 0;
|
||||
list-style-image: url("chrome://global/skin/icons/question-16.png");
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon > .button-box > .button-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 0;
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
min-width: 280px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#identity-popup-button-container {
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
|
||||
padding: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
|
||||
.popup-notification-body[popupid="addon-progress"],
|
||||
|
82
browser/themes/windows/controlcenter/panel.css
Normal file
82
browser/themes/windows/controlcenter/panel.css
Normal file
@ -0,0 +1,82 @@
|
||||
/* 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 ../../shared/controlcenter/panel.inc.css
|
||||
|
||||
/* Popup Icons */
|
||||
#identity-popup-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
padding: 0;
|
||||
list-style-image: url("chrome://browser/skin/identity.png");
|
||||
-moz-image-region: rect(0px, 64px, 64px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(64px, 64px, 128px, 0px);
|
||||
}
|
||||
|
||||
#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
|
||||
-moz-image-region: rect(128px, 64px, 192px, 0px);
|
||||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#identity-popup-content-host,
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#identity-popup-content-host {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#identity-popup-content-owner {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0 !important;
|
||||
font-weight: bold;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.verifiedDomain > #identity-popup-content-owner {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier {
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -24px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
|
||||
#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
|
||||
list-style-image: url("chrome://browser/skin/Secure24.png");
|
||||
}
|
||||
|
||||
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-container {
|
||||
min-width: 280px;
|
||||
padding: 10px;
|
||||
}
|
@ -177,6 +177,7 @@ browser.jar:
|
||||
skin/classic/browser/loop/toolbar-inverted.png (loop/toolbar-inverted.png)
|
||||
skin/classic/browser/loop/toolbar-XP.png (loop/toolbar-XP.png)
|
||||
skin/classic/browser/loop/toolbar-lunaSilver.png (loop/toolbar-lunaSilver.png)
|
||||
* skin/classic/browser/controlcenter/panel.css (controlcenter/panel.css)
|
||||
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
|
||||
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
|
||||
skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png)
|
||||
|
@ -395,6 +395,9 @@ DiskInit.h
|
||||
dlfcn.h
|
||||
dlgs.h
|
||||
dl.h
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
dns_sd.h
|
||||
#endif
|
||||
docobj.h
|
||||
dos/dosextens.h
|
||||
dos.h
|
||||
|
@ -227,7 +227,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
17|18)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
if test -d "$gonkdir/external/bluetooth/bluez"; then
|
||||
GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
|
||||
MOZ_B2G_BT=1
|
||||
@ -252,7 +252,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
19)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
@ -271,7 +271,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_FMP4=1
|
||||
;;
|
||||
21|22)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_AUDIO_OFFLOAD=1
|
||||
MOZ_OMX_DECODER=1
|
||||
MOZ_OMX_ENCODER=1
|
||||
|
@ -479,7 +479,10 @@ BluetoothGattManager::UnregisterClient(int aClientIf,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mUnregisterClientRunnable = aRunnable;
|
||||
@ -580,7 +583,7 @@ BluetoothGattManager::StartLeScan(const nsTArray<nsString>& aServiceUuids,
|
||||
size_t index = sClients->IndexOf(appUuidStr, 0 /* Start */, UuidComparator());
|
||||
|
||||
// Reject the startLeScan request if the clientIf is being used.
|
||||
if (index != sClients->NoIndex) {
|
||||
if (NS_WARN_IF(index != sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("start LE scan failed"));
|
||||
return;
|
||||
@ -738,7 +741,10 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mDisconnectRunnable = aRunnable;
|
||||
@ -782,7 +788,10 @@ BluetoothGattManager::Discover(const nsAString& aAppUuid,
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mConnId > 0);
|
||||
@ -851,7 +860,10 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mReadRemoteRssiRunnable = aRunnable;
|
||||
@ -915,7 +927,10 @@ BluetoothGattManager::RegisterNotifications(
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
@ -988,7 +1003,10 @@ BluetoothGattManager::DeregisterNotifications(
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
@ -1049,9 +1067,7 @@ BluetoothGattManager::ReadCharacteristicValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the read characteristic value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadCharacteristicValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1131,9 +1147,7 @@ BluetoothGattManager::WriteCharacteristicValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the write characteristic value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteCharacteristicValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1214,9 +1228,7 @@ BluetoothGattManager::ReadDescriptorValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the read descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1297,9 +1309,7 @@ BluetoothGattManager::WriteDescriptorValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the write descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1352,7 +1362,8 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
UuidToString(aAppUuid, uuid);
|
||||
|
||||
size_t index = sClients->IndexOf(uuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
@ -1447,7 +1458,8 @@ BluetoothGattManager::ConnectNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) {
|
||||
@ -1499,7 +1511,8 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) {
|
||||
@ -1545,7 +1558,7 @@ BluetoothGattManager::SearchCompleteNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1582,7 +1595,7 @@ BluetoothGattManager::SearchResultNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
// Save to mServices for distributing to application and discovering
|
||||
// included services, characteristics of this service later
|
||||
@ -1603,7 +1616,7 @@ BluetoothGattManager::GetCharacteristicNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1655,7 +1668,7 @@ BluetoothGattManager::GetDescriptorNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1699,7 +1712,7 @@ BluetoothGattManager::GetIncludedServiceNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -2018,6 +2031,7 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) { // operation failed
|
||||
|
@ -385,16 +385,20 @@ BluetoothDevice::UpdatePropertiesFromAdvData(const nsTArray<uint8_t>& aAdvData)
|
||||
char uuidStr[36];
|
||||
if (type == GAP_INCOMPLETE_UUID16 || type == GAP_COMPLETE_UUID16) {
|
||||
// Convert 16-bits UUID into string.
|
||||
sprintf(uuidStr, "0000%04x-0000-1000-8000-00805f9b34fb", uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID32 || type == GAP_COMPLETE_UUID32) {
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"0000%04x-0000-1000-8000-00805f9b34fb", uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID32 ||
|
||||
type == GAP_COMPLETE_UUID32) {
|
||||
// Convert 32-bits UUID into string.
|
||||
sprintf(uuidStr, "%04x%04x-0000-1000-8000-00805f9b34fb",
|
||||
uuid[1], uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID128 || type == GAP_COMPLETE_UUID128) {
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"%04x%04x-0000-1000-8000-00805f9b34fb", uuid[1], uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID128 ||
|
||||
type == GAP_COMPLETE_UUID128) {
|
||||
// Convert 128-bits UUID into string.
|
||||
sprintf(uuidStr, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
uuid[7], uuid[6], uuid[5], uuid[4],
|
||||
uuid[3], uuid[2], uuid[1], uuid[0]);
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
uuid[7], uuid[6], uuid[5], uuid[4],
|
||||
uuid[3], uuid[2], uuid[1], uuid[0]);
|
||||
}
|
||||
nsString uuidNsString;
|
||||
uuidNsString.AssignLiteral(uuidStr);
|
||||
|
@ -326,6 +326,9 @@ int
|
||||
GonkCameraHardware::AutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->autoFocus();
|
||||
}
|
||||
|
||||
@ -333,6 +336,9 @@ int
|
||||
GonkCameraHardware::CancelAutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->cancelAutoFocus();
|
||||
}
|
||||
|
||||
@ -340,8 +346,11 @@ int
|
||||
GonkCameraHardware::StartFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
|
||||
#endif
|
||||
@ -356,8 +365,11 @@ int
|
||||
GonkCameraHardware::StopFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0);
|
||||
#endif
|
||||
@ -371,6 +383,9 @@ GonkCameraHardware::StopFaceDetection()
|
||||
int
|
||||
GonkCameraHardware::TakePicture()
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE);
|
||||
}
|
||||
|
||||
@ -383,6 +398,9 @@ GonkCameraHardware::CancelTakePicture()
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
const String8 s = aParams.Flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@ -390,6 +408,9 @@ GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
nsresult
|
||||
GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
const String8 s = mCamera->getParameters();
|
||||
return aParams.Unflatten(s);
|
||||
}
|
||||
@ -398,6 +419,9 @@ GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
String8 s = aParams.flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@ -405,8 +429,10 @@ GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
void
|
||||
GonkCameraHardware::PullParameters(CameraParameters& aParams)
|
||||
{
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -414,6 +440,9 @@ int
|
||||
GonkCameraHardware::StartPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->startPreview();
|
||||
}
|
||||
|
||||
@ -421,16 +450,20 @@ void
|
||||
GonkCameraHardware::StopPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
mCamera->stopPreview();
|
||||
if (!mClosing) {
|
||||
mCamera->stopPreview();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GonkCameraHardware::StartRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
int rv = OK;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
rv = mCamera->startRecording();
|
||||
int rv = mCamera->startRecording();
|
||||
if (rv != OK) {
|
||||
DOM_CAMERA_LOGE("mHardware->startRecording() failed with status %d", rv);
|
||||
}
|
||||
@ -441,6 +474,9 @@ int
|
||||
GonkCameraHardware::StopRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
mCamera->stopRecording();
|
||||
return OK;
|
||||
}
|
||||
@ -456,12 +492,17 @@ GonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
|
||||
void
|
||||
GonkCameraHardware::ReleaseRecordingFrame(const sp<IMemory>& aFrame)
|
||||
{
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->storeMetaDataInBuffers(aEnabled);
|
||||
}
|
||||
|
@ -218,10 +218,9 @@ NfcContentHelper.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId, tabId) {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId) {
|
||||
cpmm.sendAsyncMessage("NFC:NotifyUserAcceptedP2P", {
|
||||
appId: appId,
|
||||
tabId: tabId
|
||||
appId: appId
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -292,7 +292,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
message.target.sendAsyncMessage(message.name + "Response", respMsg);
|
||||
},
|
||||
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId, tabId) {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId) {
|
||||
let target = this.peerTargets[appId];
|
||||
let sessionToken = SessionHelper.getCurrentP2PToken();
|
||||
let isValid = (sessionToken != null) && (target != null);
|
||||
@ -301,7 +301,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return;
|
||||
}
|
||||
|
||||
this.notifyDOMEvent(target, {tabId: tabId,
|
||||
this.notifyDOMEvent(target, {tabId: this.focusApp,
|
||||
event: NFC.PEER_EVENT_READY,
|
||||
sessionToken: sessionToken});
|
||||
},
|
||||
@ -408,7 +408,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
this.checkP2PRegistration(message);
|
||||
return null;
|
||||
case "NFC:NotifyUserAcceptedP2P":
|
||||
this.notifyUserAcceptedP2P(message.data.appId, message.data.tabId);
|
||||
this.notifyUserAcceptedP2P(message.data.appId);
|
||||
return null;
|
||||
case "NFC:NotifySendFileStatus":
|
||||
// Upon receiving the status of sendFile operation, send the response
|
||||
|
@ -124,7 +124,7 @@ interface nsINfcBrowserAPI : nsISupports
|
||||
in boolean isFocus);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f0ed35c5-3f59-4806-b6bb-e77b879887af)]
|
||||
[scriptable, uuid(75f0c8c0-2e5a-491f-a75d-4f3849c4feec)]
|
||||
interface nsINfcContentHelper : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -277,10 +277,8 @@ interface nsINfcContentHelper : nsISupports
|
||||
*
|
||||
* @param appId
|
||||
* Application ID that is capable of handling NFC_EVENT_PEER_READY event
|
||||
* @param tabId
|
||||
* Tab Id of the window calling this interface.
|
||||
*/
|
||||
void notifyUserAcceptedP2P(in unsigned long appId, in uint64_t tabId);
|
||||
void notifyUserAcceptedP2P(in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Notify the status of sendFile operation to parent process
|
||||
|
@ -420,7 +420,7 @@ MozNFCImpl.prototype = {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(manifestUrl) {
|
||||
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
||||
// Notify chrome process of user's acknowledgement
|
||||
this._nfcContentHelper.notifyUserAcceptedP2P(appID, this._tabId);
|
||||
this._nfcContentHelper.notifyUserAcceptedP2P(appID);
|
||||
},
|
||||
|
||||
notifySendFileStatus: function notifySendFileStatus(status, requestId) {
|
||||
|
@ -22,7 +22,8 @@ NS_IMPL_ISUPPORTS(PresentationDeviceManager,
|
||||
nsIPresentationDeviceManager,
|
||||
nsIPresentationDeviceListener,
|
||||
nsIPresentationDeviceEventListener,
|
||||
nsIObserver)
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
PresentationDeviceManager::PresentationDeviceManager()
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsIPresentationDeviceManager.h"
|
||||
#include "nsIPresentationDeviceProvider.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -20,6 +21,7 @@ class PresentationDeviceManager final : public nsIPresentationDeviceManager
|
||||
, public nsIPresentationDeviceListener
|
||||
, public nsIPresentationDeviceEventListener
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
493
dom/presentation/provider/MulticastDNSDeviceProvider.cpp
Normal file
493
dom/presentation/provider/MulticastDNSDeviceProvider.cpp
Normal file
@ -0,0 +1,493 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MulticastDNSDeviceProvider.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIPresentationDevice.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
inline static PRLogModuleInfo*
|
||||
GetProviderLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MulticastDNSDeviceProvider");
|
||||
return log;
|
||||
}
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) PR_LOG(GetProviderLog(), PR_LOG_NOTICE, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) PR_LOG(GetProviderLog(), PR_LOG_ERROR, (__VA_ARGS__))
|
||||
|
||||
#define SERVICE_TYPE "_mozilla_papi._tcp."
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace presentation {
|
||||
|
||||
/**
|
||||
* This wrapper is used to break circular-reference problem.
|
||||
*/
|
||||
class DNSServiceWrappedListener final
|
||||
: public nsIDNSServiceDiscoveryListener
|
||||
, public nsIDNSRegistrationListener
|
||||
, public nsIDNSServiceResolveListener
|
||||
, public nsITCPPresentationServerListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_SAFE_NSIDNSSERVICEDISCOVERYLISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSIDNSREGISTRATIONLISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSIDNSSERVICERESOLVELISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSITCPPRESENTATIONSERVERLISTENER(mListener)
|
||||
|
||||
explicit DNSServiceWrappedListener() = default;
|
||||
|
||||
nsresult SetListener(MulticastDNSDeviceProvider* aListener)
|
||||
{
|
||||
mListener = aListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~DNSServiceWrappedListener() = default;
|
||||
|
||||
MulticastDNSDeviceProvider* mListener = nullptr;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(DNSServiceWrappedListener,
|
||||
nsIDNSServiceDiscoveryListener,
|
||||
nsIDNSRegistrationListener,
|
||||
nsIDNSServiceResolveListener,
|
||||
nsITCPPresentationServerListener)
|
||||
|
||||
NS_IMPL_ISUPPORTS(MulticastDNSDeviceProvider,
|
||||
nsIPresentationDeviceProvider,
|
||||
nsIDNSServiceDiscoveryListener,
|
||||
nsIDNSRegistrationListener,
|
||||
nsIDNSServiceResolveListener,
|
||||
nsITCPPresentationServerListener)
|
||||
|
||||
MulticastDNSDeviceProvider::~MulticastDNSDeviceProvider()
|
||||
{
|
||||
Uninit();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::Init()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
mMulticastDNS = do_GetService(DNSSERVICEDISCOVERY_CONTRACT_ID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWrappedListener = new DNSServiceWrappedListener();
|
||||
if (NS_WARN_IF(!mWrappedListener)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mWrappedListener->SetListener(this)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPresentationServer = do_CreateInstance("@mozilla.org/presentation-device/tcp-presentation-server;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->Init(EmptyCString(), 0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::Uninit()
|
||||
{
|
||||
if (!mInitialized) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mPresentationServer) {
|
||||
mPresentationServer->Close();
|
||||
mPresentationServer = nullptr;
|
||||
}
|
||||
|
||||
if (mDiscoveryRequest) {
|
||||
mDiscoveryRequest->Cancel(NS_OK);
|
||||
mDiscoveryRequest = nullptr;
|
||||
}
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
mMulticastDNS = nullptr;
|
||||
|
||||
if (mWrappedListener) {
|
||||
mWrappedListener->SetListener(nullptr);
|
||||
mWrappedListener = nullptr;
|
||||
}
|
||||
|
||||
mInitialized = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::RegisterService(uint32_t aPort)
|
||||
{
|
||||
LOG_I("RegisterService: %d", aPort);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> serviceInfo = do_CreateInstance(DNSSERVICEINFO_CONTRACT_ID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetServiceType(NS_LITERAL_CSTRING(SERVICE_TYPE))))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetPort(aPort)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
return mMulticastDNS->RegisterService(serviceInfo, mWrappedListener, getter_AddRefs(mRegisterRequest));
|
||||
}
|
||||
|
||||
// nsIPresentationDeviceProvider
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::GetListener(nsIPresentationDeviceListener** aListener)
|
||||
{
|
||||
if (NS_WARN_IF(!aListener)) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener = do_QueryReferent(mDeviceListener);
|
||||
listener.forget(aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::SetListener(nsIPresentationDeviceListener* aListener)
|
||||
{
|
||||
mDeviceListener = do_GetWeakReference(aListener);
|
||||
|
||||
nsresult rv;
|
||||
if (mDeviceListener) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = Init()))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = Uninit()))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::ForceDiscovery()
|
||||
{
|
||||
LOG_I("ForceDiscovery");
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(mMulticastDNS);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mDiscoveryRequest) {
|
||||
mDiscoveryRequest->Cancel(NS_OK);
|
||||
mDiscoveryRequest = nullptr;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->StartDiscovery(
|
||||
NS_LITERAL_CSTRING(SERVICE_TYPE),
|
||||
mWrappedListener,
|
||||
getter_AddRefs(mDiscoveryRequest))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSServiceDiscoveryListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnDiscoveryStarted(const nsACString& aServiceType)
|
||||
{
|
||||
LOG_I("OnDiscoveryStarted");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnDiscoveryStopped(const nsACString& aServiceType)
|
||||
{
|
||||
LOG_I("OnDiscoveryStopped");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceFound(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv ;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceFound: %s", serviceName.get());
|
||||
|
||||
if (mRegisteredName == serviceName) {
|
||||
LOG_I("ignore self");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
if (NS_SUCCEEDED(mPresentationServer->GetTCPDevice(serviceName,
|
||||
getter_AddRefs(device)))) {
|
||||
LOG_I("device exists");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMulticastDNS) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->ResolveService(aServiceInfo, mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceLost(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceLost: %s", serviceName.get());
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
if (NS_FAILED(mPresentationServer->GetTCPDevice(serviceName, getter_AddRefs(device)))) {
|
||||
return NS_OK; // ignore non-existing device;
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(mPresentationServer->RemoveTCPDevice(serviceName)));
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
GetListener(getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
listener->RemoveDevice(device);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnStartDiscoveryFailed(const nsACString& aServiceType, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnStartDiscoveryFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnStopDiscoveryFailed(const nsACString& aServiceType, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnStopDiscoveryFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSRegistrationListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceRegistered(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString name;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(name)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceRegistered (%s)", name.get());
|
||||
mRegisteredName = name;
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetId(name)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceUnregistered(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
LOG_I("OnServiceUnregistered");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnRegistrationFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnRegistrationFailed: %d", aErrorCode);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (aErrorCode == nsIDNSRegistrationListener::ERROR_SERVICE_NOT_RUNNING) {
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnUnregistrationFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnUnregistrationFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSServiceResolveListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceResolved(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceResolved: %s", serviceName.get());
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
GetListener(getter_AddRefs(listener));
|
||||
|
||||
if (NS_SUCCEEDED(mPresentationServer->GetTCPDevice(serviceName,
|
||||
getter_AddRefs(device)))) {
|
||||
NS_WARN_IF(NS_FAILED(mPresentationServer->RemoveTCPDevice(serviceName)));
|
||||
if (listener) {
|
||||
NS_WARN_IF(NS_FAILED(listener->RemoveDevice(device)));
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetHost(host)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString serviceType;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceType(serviceType)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->CreateTCPDevice(serviceName,
|
||||
serviceName,
|
||||
serviceType,
|
||||
host,
|
||||
port,
|
||||
getter_AddRefs(device))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
listener->AddDevice(device);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnResolveFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnResolveFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsITCPPresentationServerListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnClose(nsresult aReason)
|
||||
{
|
||||
LOG_I("OnClose: %x", aReason);
|
||||
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(aReason);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(aReason)) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->Init(EmptyCString(), 0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace presentation
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
64
dom/presentation/provider/MulticastDNSDeviceProvider.h
Normal file
64
dom/presentation/provider/MulticastDNSDeviceProvider.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
||||
#define mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIPresentationDeviceProvider.h"
|
||||
#include "nsITCPPresentationServer.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace presentation {
|
||||
|
||||
class DNSServiceWrappedListener;
|
||||
class MulticastDNSService;
|
||||
|
||||
class MulticastDNSDeviceProvider final
|
||||
: public nsIPresentationDeviceProvider
|
||||
, public nsIDNSServiceDiscoveryListener
|
||||
, public nsIDNSRegistrationListener
|
||||
, public nsIDNSServiceResolveListener
|
||||
, public nsITCPPresentationServerListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPRESENTATIONDEVICEPROVIDER
|
||||
NS_DECL_NSIDNSSERVICEDISCOVERYLISTENER
|
||||
NS_DECL_NSIDNSREGISTRATIONLISTENER
|
||||
NS_DECL_NSIDNSSERVICERESOLVELISTENER
|
||||
NS_DECL_NSITCPPRESENTATIONSERVERLISTENER
|
||||
|
||||
explicit MulticastDNSDeviceProvider() = default;
|
||||
nsresult Init();
|
||||
nsresult Uninit();
|
||||
|
||||
private:
|
||||
virtual ~MulticastDNSDeviceProvider();
|
||||
nsresult RegisterService(uint32_t aPort);
|
||||
|
||||
bool mInitialized = false;
|
||||
nsWeakPtr mDeviceListener;
|
||||
nsCOMPtr<nsITCPPresentationServer> mPresentationServer;
|
||||
nsCOMPtr<nsIDNSServiceDiscovery> mMulticastDNS;
|
||||
nsRefPtr<DNSServiceWrappedListener> mWrappedListener;
|
||||
|
||||
nsCOMPtr<nsICancelable> mDiscoveryRequest;
|
||||
nsCOMPtr<nsICancelable> mRegisterRequest;
|
||||
|
||||
nsCString mRegisteredName;
|
||||
};
|
||||
|
||||
} // namespace presentation
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MulticastDNSDeviceProvider.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#define MULTICAST_DNS_PROVIDER_CID \
|
||||
{0x814f947a, 0x52f7, 0x41c9, \
|
||||
{ 0x94, 0xa1, 0x36, 0x84, 0x79, 0x72, 0x84, 0xac }}
|
||||
|
||||
#define MULTICAST_DNS_PROVIDER_CONTRACT_ID "@mozilla.org/presentation-device/multicastdns-provider;1"
|
||||
|
||||
using mozilla::dom::presentation::MulticastDNSDeviceProvider;
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(MulticastDNSDeviceProvider)
|
||||
NS_DEFINE_NAMED_CID(MULTICAST_DNS_PROVIDER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kPresentationDeviceProviderCIDs[] = {
|
||||
{ &kMULTICAST_DNS_PROVIDER_CID, false, nullptr, MulticastDNSDeviceProviderConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry kPresentationDeviceProviderContracts[] = {
|
||||
{ MULTICAST_DNS_PROVIDER_CONTRACT_ID, &kMULTICAST_DNS_PROVIDER_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry kPresentationDeviceProviderCategories[] = {
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16
|
||||
{ PRESENTATION_DEVICE_PROVIDER_CATEGORY, "MulticastDNSDeviceProvider", MULTICAST_DNS_PROVIDER_CONTRACT_ID},
|
||||
#endif
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module kPresentationDeviceProviderModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kPresentationDeviceProviderCIDs,
|
||||
kPresentationDeviceProviderContracts,
|
||||
kPresentationDeviceProviderCategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(PresentationDeviceProviderModule) = &kPresentationDeviceProviderModule;
|
@ -8,3 +8,13 @@ EXTRA_COMPONENTS += [
|
||||
'BuiltinProviders.manifest',
|
||||
'TCPPresentationServer.js'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MulticastDNSDeviceProvider.cpp',
|
||||
'PresentationDeviceProviderModule.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -0,0 +1,255 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, manager: Cm, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const INFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
|
||||
const PROVIDER_CONTRACT_ID = "@mozilla.org/presentation-device/multicastdns-provider;1";
|
||||
const SD_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1";
|
||||
const UUID_CONTRACT_ID = "@mozilla.org/uuid-generator;1";
|
||||
|
||||
let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
function MockFactory(aClass) {
|
||||
this._cls = aClass;
|
||||
}
|
||||
MockFactory.prototype = {
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
switch(typeof(this._cls)) {
|
||||
case "function":
|
||||
return new this._cls().QueryInterface(aIID);
|
||||
case "object":
|
||||
return this._cls.QueryInterface(aIID);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
lockFactory: function(aLock) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
|
||||
};
|
||||
|
||||
function ContractHook(aContractID, aClass) {
|
||||
this._contractID = aContractID;
|
||||
this.classID = Cc[UUID_CONTRACT_ID].getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
this._newFactory = new MockFactory(aClass);
|
||||
|
||||
if (!this.hookedMap.has(this._contractID)) {
|
||||
this.hookedMap.set(this._contractID, new Array());
|
||||
}
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
ContractHook.prototype = {
|
||||
hookedMap: new Map(), // remember only the most original factory.
|
||||
|
||||
init: function() {
|
||||
this.reset();
|
||||
|
||||
let oldContract = this.unregister();
|
||||
this.hookedMap.get(this._contractID).push(oldContract);
|
||||
registrar.registerFactory(this.classID, "", this._contractID, this._newFactory);
|
||||
|
||||
do_register_cleanup(() => { this.cleanup.apply(this); });
|
||||
},
|
||||
|
||||
reset: function() {},
|
||||
|
||||
cleanup: function() {
|
||||
this.reset();
|
||||
|
||||
this.unregister();
|
||||
let prevContract = this.hookedMap.get(this._contractID).pop();
|
||||
|
||||
if (prevContract.factory) {
|
||||
registrar.registerFactory(prevContract.classID, "", this._contractID, prevContract.factory);
|
||||
}
|
||||
},
|
||||
|
||||
unregister: function() {
|
||||
var classID, factory;
|
||||
|
||||
try {
|
||||
classID = registrar.contractIDToCID(this._contractID);
|
||||
factory = Cm.getClassObject(Cc[this._contractID], Ci.nsIFactory);
|
||||
} catch (ex) {
|
||||
classID = "";
|
||||
factory = null;
|
||||
}
|
||||
|
||||
if (factory) {
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
}
|
||||
|
||||
return { classID: classID, factory: factory };
|
||||
}
|
||||
};
|
||||
|
||||
function MockDNSServiceInfo() {}
|
||||
MockDNSServiceInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceInfo]),
|
||||
|
||||
set host(aHost) {
|
||||
this._host = aHost;
|
||||
},
|
||||
|
||||
get host() {
|
||||
return this._host;
|
||||
},
|
||||
|
||||
set port(aPort) {
|
||||
this._port = aPort;
|
||||
},
|
||||
|
||||
get port() {
|
||||
return this._port;
|
||||
},
|
||||
|
||||
set serviceName(aServiceName) {
|
||||
this._serviceName = aServiceName;
|
||||
},
|
||||
|
||||
get serviceName() {
|
||||
return this._serviceName;
|
||||
},
|
||||
|
||||
set serviceType(aServiceType) {
|
||||
this._serviceType = aServiceType;
|
||||
},
|
||||
|
||||
get serviceType() {
|
||||
return this._serviceType;
|
||||
},
|
||||
|
||||
set domainName(aDomainName) {
|
||||
this._domainName = aDomainName;
|
||||
},
|
||||
|
||||
get domainName() {
|
||||
return this._domainName;
|
||||
},
|
||||
|
||||
set attributes(aAttributes) {
|
||||
this._attributes = aAttributes;
|
||||
},
|
||||
|
||||
get attributes() {
|
||||
return this._attributes;
|
||||
}
|
||||
};
|
||||
|
||||
function TestPresentationDeviceListener() {}
|
||||
TestPresentationDeviceListener.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener]),
|
||||
|
||||
addDevice: function(device) {},
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {}
|
||||
};
|
||||
|
||||
function createDevice(host, port, serviceName, serviceType, domainName, attributes) {
|
||||
let device = new MockDNSServiceInfo();
|
||||
device.host = host || "";
|
||||
device.port = port || 0;
|
||||
device.serviceName = serviceName || "";
|
||||
device.serviceType = serviceType || "";
|
||||
device.domainName = domainName || "";
|
||||
device.attributes = attributes || null;
|
||||
return device;
|
||||
}
|
||||
|
||||
function registerService() {
|
||||
let mockObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {},
|
||||
registerService: function(serviceInfo, listener) {
|
||||
this.serviceRegistered++;
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {
|
||||
this.serviceUnregistered++;
|
||||
}.bind(this)
|
||||
}
|
||||
},
|
||||
resolveService: function(serviceInfo, listener) {},
|
||||
serviceRegistered: 0,
|
||||
serviceUnregistered: 0
|
||||
};
|
||||
let contractHook = new ContractHook(SD_CONTRACT_ID, mockObj);
|
||||
|
||||
Assert.equal(mockObj.serviceRegistered, 0);
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
Assert.equal(mockObj.serviceRegistered, 0);
|
||||
provider.listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener, Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) {},
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {},
|
||||
};
|
||||
Assert.equal(mockObj.serviceRegistered, 1);
|
||||
|
||||
Assert.equal(mockObj.serviceUnregistered, 0);
|
||||
provider.listener = null;
|
||||
Assert.equal(mockObj.serviceUnregistered, 1);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function addDevice() {
|
||||
let mockDevice = createDevice("device.local", 12345, "service.name", "_mozilla_papi._tcp");
|
||||
let mockObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {
|
||||
listener.onDiscoveryStarted(serviceType);
|
||||
listener.onServiceFound(createDevice("", 0, mockDevice.serviceName, mockDevice.serviceType));
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {}
|
||||
}
|
||||
},
|
||||
registerService: function(serviceInfo, listener) {},
|
||||
resolveService: function(serviceInfo, listener) {
|
||||
Assert.equal(serviceInfo.serviceName, mockDevice.serviceName);
|
||||
Assert.equal(serviceInfo.serviceType, mockDevice.serviceType);
|
||||
listener.onServiceResolved(createDevice(mockDevice.host, mockDevice.port, mockDevice.serviceName, mockDevice.serviceType));
|
||||
}
|
||||
};
|
||||
let contractHook = new ContractHook(SD_CONTRACT_ID, mockObj);
|
||||
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener, Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) { this.devices.push(device); },
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {},
|
||||
devices: []
|
||||
};
|
||||
provider.listener = listener;
|
||||
|
||||
Assert.equal(listener.devices.length, 0);
|
||||
provider.forceDiscovery();
|
||||
Assert.equal(listener.devices.length, 1);
|
||||
|
||||
provider.listener = null;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let infoHook = new ContractHook(INFO_CONTRACT_ID, MockDNSServiceInfo);
|
||||
|
||||
add_test(registerService);
|
||||
add_test(addDevice);
|
||||
|
||||
run_next_test();
|
||||
}
|
@ -2,5 +2,6 @@
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_multicast_dns_device_provider.js]
|
||||
[test_presentation_device_manager.js]
|
||||
[test_tcp_control_channel.js]
|
||||
|
@ -368,7 +368,7 @@ nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
|
||||
}
|
||||
|
||||
already_AddRefed<nsVolume>
|
||||
nsVolumeService::FindVolumeByName(const nsAString& aName)
|
||||
nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
|
||||
{
|
||||
mArrayMonitor.AssertCurrentThreadOwns();
|
||||
|
||||
@ -377,52 +377,34 @@ nsVolumeService::FindVolumeByName(const nsAString& aName)
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
|
||||
if (vol->Name().Equals(aName)) {
|
||||
if (aIndex) {
|
||||
*aIndex = volIndex;
|
||||
}
|
||||
return vol.forget();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<nsVolume>
|
||||
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/)
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
|
||||
nsRefPtr<nsVolume> vol;
|
||||
vol = FindVolumeByName(aName);
|
||||
if (vol) {
|
||||
return vol.forget();
|
||||
}
|
||||
// Volume not found - add a new one
|
||||
vol = new nsVolume(aName);
|
||||
vol->SetIsFake(aIsFake);
|
||||
mVolumeArray.AppendElement(vol);
|
||||
return vol.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
|
||||
nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString volName;
|
||||
aVolume->GetName(volName);
|
||||
bool aIsFake;
|
||||
aVolume->GetIsFake(&aIsFake);
|
||||
nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
|
||||
if (vol->Equals(aVolume)) {
|
||||
// Nothing has really changed. Don't bother telling anybody.
|
||||
return;
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
nsVolume::Array::index_type volIndex;
|
||||
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
|
||||
if (!vol) {
|
||||
mVolumeArray.AppendElement(aVolume);
|
||||
} else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
|
||||
// Ignore if nothing changed or if a fake tries to override a real volume.
|
||||
return;
|
||||
} else {
|
||||
mVolumeArray.ReplaceElementAt(volIndex, aVolume);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vol->IsFake() && aIsFake) {
|
||||
// Prevent an incoming fake volume from overriding an existing real volume.
|
||||
return;
|
||||
}
|
||||
|
||||
vol->Set(aVolume);
|
||||
|
||||
if (!aNotifyObservers) {
|
||||
return;
|
||||
}
|
||||
@ -431,8 +413,8 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
|
||||
if (!obs) {
|
||||
return;
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
|
||||
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
|
||||
obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -471,9 +453,7 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// UpdateVolume expects the volume passed in to NOT be the
|
||||
// same pointer as what CreateOrFindVolumeByName would return,
|
||||
// which is why we allocate a temporary volume here.
|
||||
// Clone the existing volume so we can replace it
|
||||
nsRefPtr<nsVolume> volume = new nsVolume(name);
|
||||
volume->Set(vol);
|
||||
volume->SetState(state);
|
||||
@ -502,15 +482,15 @@ nsVolumeService::RemoveFakeVolume(const nsAString& name)
|
||||
void
|
||||
nsVolumeService::RemoveVolumeByName(const nsAString& aName)
|
||||
{
|
||||
nsRefPtr<nsVolume> vol;
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
vol = FindVolumeByName(aName);
|
||||
nsVolume::Array::index_type volIndex;
|
||||
nsRefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
|
||||
if (!vol) {
|
||||
return;
|
||||
}
|
||||
mVolumeArray.RemoveElementAt(volIndex);
|
||||
}
|
||||
if (!vol) {
|
||||
return;
|
||||
}
|
||||
mVolumeArray.RemoveElement(vol);
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
void DumpNoLock(const char* aLabel);
|
||||
|
||||
// To use this function, you have to create a new volume and pass it in.
|
||||
void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
|
||||
void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
|
||||
void UpdateVolumeIOThread(const Volume* aVolume);
|
||||
|
||||
void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
|
||||
@ -61,8 +61,9 @@ private:
|
||||
void CheckMountLock(const nsAString& aMountLockName,
|
||||
const nsAString& aMountLockState);
|
||||
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
|
||||
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
|
||||
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
|
||||
nsVolume::Array::index_type* aIndex = nullptr);
|
||||
|
||||
Monitor mArrayMonitor;
|
||||
nsVolume::Array mVolumeArray;
|
||||
|
110
dom/telephony/gonk/TelephonyUtils.jsm
Normal file
110
dom/telephony/gonk/TelephonyUtils.jsm
Normal file
@ -0,0 +1,110 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TelephonyUtils"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
/* global TelephonyService */
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"TelephonyService",
|
||||
"@mozilla.org/telephony/telephonyservice;1",
|
||||
"nsITelephonyService");
|
||||
|
||||
function getCurrentCalls(aFilter) {
|
||||
if (aFilter === undefined) {
|
||||
aFilter = call => true;
|
||||
}
|
||||
|
||||
let calls = [];
|
||||
|
||||
// nsITelephonyService.enumerateCalls is synchronous.
|
||||
TelephonyService.enumerateCalls({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
enumerateCallStateComplete: function() {},
|
||||
enumerateCallState: function(call) {
|
||||
if (aFilter(call)) {
|
||||
calls.push(call);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return calls;
|
||||
}
|
||||
|
||||
this.TelephonyUtils = {
|
||||
/**
|
||||
* Check whether there are any calls.
|
||||
*
|
||||
* @param aClientId [optional] If provided, only check on aClientId
|
||||
* @return boolean
|
||||
*/
|
||||
hasAnyCalls: function(aClientId) {
|
||||
let calls = getCurrentCalls(call => {
|
||||
if (aClientId !== undefined && call.clientId !== aClientId) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return calls.length !== 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether there are any connected calls.
|
||||
*
|
||||
* @param aClientId [optional] If provided, only check on aClientId
|
||||
* @return boolean
|
||||
*/
|
||||
hasConnectedCalls: function(aClientId) {
|
||||
let calls = getCurrentCalls(call => {
|
||||
if (aClientId !== undefined && call.clientId !== aClientId) {
|
||||
return false;
|
||||
}
|
||||
return call.callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED;
|
||||
});
|
||||
|
||||
return calls.length !== 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a promise which will be resolved when there are no calls.
|
||||
*
|
||||
* @param aClientId [optional] only check on aClientId if provided
|
||||
* @return Promise
|
||||
*/
|
||||
waitForNoCalls: function(aClientId) {
|
||||
if (!this.hasAnyCalls(aClientId)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let self = this;
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
|
||||
enumerateCallStateComplete: function() {},
|
||||
enumerateCallState: function() {},
|
||||
callStateChanged: function() {
|
||||
if (!self.hasAnyCalls(aClientId)) {
|
||||
TelephonyService.unregisterListener(this);
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
conferenceCallStateChanged: function() {},
|
||||
supplementaryServiceNotification: function() {},
|
||||
notifyError: function() {},
|
||||
notifyCdmaCallWaiting: function() {},
|
||||
notifyConferenceError: function() {}
|
||||
};
|
||||
|
||||
TelephonyService.registerListener(listener);
|
||||
});
|
||||
}
|
||||
};
|
@ -72,7 +72,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
'gonk/TelephonyService.manifest',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'gonk/DialNumberUtils.jsm'
|
||||
'gonk/DialNumberUtils.jsm',
|
||||
'gonk/TelephonyUtils.jsm',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -1107,12 +1107,19 @@ let emulator = (function() {
|
||||
|
||||
let promises = [];
|
||||
|
||||
let promise = gWaitForEvent(connection, "radiostatechange", event => {
|
||||
promises.push(gWaitForEvent(connection, "radiostatechange", event => {
|
||||
let state = connection.radioState;
|
||||
log("current radioState: " + state);
|
||||
return state == desiredRadioState;
|
||||
});
|
||||
promises.push(promise);
|
||||
}));
|
||||
|
||||
// Wait for icc status to finish updating. Please see bug 1169504 for the
|
||||
// reason why we need this.
|
||||
promises.push(gWaitForEvent(connection, "iccchange", event => {
|
||||
let iccId = connection.iccId;
|
||||
log("current iccId: " + iccId);
|
||||
return !!iccId === enabled;
|
||||
}));
|
||||
|
||||
promises.push(connection.setRadioEnabled(enabled));
|
||||
|
||||
|
@ -54,4 +54,5 @@ qemu = true
|
||||
[test_redundant_operations.js]
|
||||
[test_swap_held_and_active.js]
|
||||
[test_system_message_telephony_call_ended.js]
|
||||
[test_TelephonyUtils.js]
|
||||
[test_temporary_clir.js]
|
||||
|
91
dom/telephony/test/marionette/test_TelephonyUtils.js
Normal file
91
dom/telephony/test/marionette/test_TelephonyUtils.js
Normal file
@ -0,0 +1,91 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_CONTEXT = "chrome";
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"TelephonyService",
|
||||
"@mozilla.org/telephony/telephonyservice;1",
|
||||
"nsIGonkTelephonyService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelephonyUtils",
|
||||
"resource://gre/modules/TelephonyUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
|
||||
let ns = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", ns);
|
||||
return ns;
|
||||
});
|
||||
|
||||
const number = "0912345678";
|
||||
|
||||
function dial() {
|
||||
return new Promise(resolve => {
|
||||
TelephonyService.dial(0, number, false, {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
|
||||
notifyDialCallSuccess: function() { resolve(); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForStateChanged() {
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
|
||||
callStateChanged: function(length, allInfo) {
|
||||
resolve(allInfo);
|
||||
TelephonyService.unregisterListener(listener);
|
||||
},
|
||||
conferenceCallStateChanged: function() {},
|
||||
supplementaryServiceNotification: function() {},
|
||||
notifyError: function() {},
|
||||
notifyCdmaCallWaiting: function() {},
|
||||
notifyConferenceError: function() {}
|
||||
};
|
||||
|
||||
TelephonyService.registerListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
function test_noCall() {
|
||||
log("== test_noCall ==");
|
||||
is(TelephonyUtils.hasAnyCalls(), false, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
|
||||
return TelephonyUtils.waitForNoCalls();
|
||||
}
|
||||
|
||||
function test_oneCall() {
|
||||
log("== test_oneCall ==");
|
||||
|
||||
return dial()
|
||||
.then(() => {
|
||||
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
|
||||
})
|
||||
.then(() => {
|
||||
let p = waitForStateChanged();
|
||||
emulator.runCmd("gsm accept " + number);
|
||||
return p;
|
||||
})
|
||||
.then(allInfo => {
|
||||
is(allInfo[0].callState, Ci.nsITelephonyService.CALL_STATE_CONNECTED);
|
||||
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), true, "hasConnectedCalls");
|
||||
})
|
||||
.then(() => {
|
||||
let p = TelephonyUtils.waitForNoCalls();
|
||||
emulator.runCmd("gsm cancel " + number);
|
||||
return p;
|
||||
});
|
||||
}
|
||||
|
||||
test_noCall()
|
||||
.then(test_oneCall)
|
||||
.catch(error => ok(false, "Promise reject: " + error))
|
||||
.then(finish);
|
@ -416,7 +416,7 @@ var WifiManager = (function() {
|
||||
let currentNetwork = Object.create(null);
|
||||
currentNetwork.netId = manager.connectionInfo.id;
|
||||
|
||||
manager.getNetworkConfiguration(currentNetwork, function (){
|
||||
manager.getNetworkConfiguration(currentNetwork, function () {
|
||||
curNetworkKey = getNetworkKey(currentNetwork);
|
||||
|
||||
// Add additional information to static ip configuration
|
||||
@ -435,15 +435,19 @@ var WifiManager = (function() {
|
||||
// If the ssid of current connection is the same as configured ssid
|
||||
// It means we need update current connection to use static IP address.
|
||||
if (setNetworkKey == curNetworkKey) {
|
||||
// Use configureInterface directly doesn't work, the network iterface
|
||||
// Use configureInterface directly doesn't work, the network interface
|
||||
// and routing table is changed but still cannot connect to network
|
||||
// so the workaround here is disable interface the enable again to
|
||||
// trigger network reconnect with static ip.
|
||||
gNetworkService.disableInterface(manager.ifname, function (ok) {
|
||||
gNetworkService.enableInterface(manager.ifname, function (ok) {
|
||||
callback(ok);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
callback(true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -3494,7 +3498,7 @@ WifiWorker.prototype = {
|
||||
},
|
||||
|
||||
setStaticIpMode: function(msg) {
|
||||
const message = "WifiManager:setStaticMode:Return";
|
||||
const message = "WifiManager:setStaticIpMode:Return";
|
||||
let self = this;
|
||||
let network = msg.data.network;
|
||||
let info = msg.data.info;
|
||||
|
@ -433,6 +433,23 @@ let gTestSuite = (function() {
|
||||
.then(event => event.target.result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given network to static ip mode.
|
||||
*
|
||||
* Resolve when we set static ip mode successfully; reject when any error
|
||||
* occurs.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setStaticIpMode(aNetwork, aConfig) {
|
||||
let request = wifiManager.setStaticIpMode(aNetwork, aConfig);
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(event => event.target.result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a request to scan all wifi available networks.
|
||||
*
|
||||
@ -1025,6 +1042,117 @@ let gTestSuite = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute 'netcfg' shell and parse the result.
|
||||
*
|
||||
* Resolve when the executing is successful and reject otherwise.
|
||||
*
|
||||
* Fulfill params: Command result object, each key of which is the interface
|
||||
* name and value is { ip(string), prefix(string) }.
|
||||
* Reject params: String that indicates the reason of rejection.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function exeAndParseNetcfg() {
|
||||
return runEmulatorShellSafe(['netcfg'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
|
||||
// eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
|
||||
// rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
|
||||
// rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
|
||||
// rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
|
||||
// wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
|
||||
// sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
|
||||
// rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
|
||||
//
|
||||
let netcfgResult = {};
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 5) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[0];
|
||||
let [ip, prefix] = tokens[2].split('/');
|
||||
netcfgResult[ifname] = { ip: ip, prefix: prefix };
|
||||
});
|
||||
log("netcfg result:" + JSON.stringify(netcfgResult));
|
||||
|
||||
return netcfgResult;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute 'ip route' and parse the result.
|
||||
*
|
||||
* Resolve when the executing is successful and reject otherwise.
|
||||
*
|
||||
* Fulfill params: Command result object, each key of which is the interface
|
||||
* name and value is { src(string), gateway(string),
|
||||
* default(boolean) }.
|
||||
* Reject params: String that indicates the reason of rejection.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function exeAndParseIpRoute() {
|
||||
return runEmulatorShellSafe(['ip', 'route'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// 10.0.2.4 via 10.0.2.2 dev rmnet0
|
||||
// 10.0.2.3 via 10.0.2.2 dev rmnet0
|
||||
// 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
|
||||
// 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
|
||||
// 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
|
||||
// default via 10.0.2.2 dev rmnet0
|
||||
// default via 10.0.2.2 dev eth0 metric 2
|
||||
//
|
||||
|
||||
let ipRouteResult = {};
|
||||
|
||||
// Parse source ip for each interface.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.trim().split(/\s+/);
|
||||
let srcIndex = tokens.indexOf('src');
|
||||
if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[2];
|
||||
let src = tokens[srcIndex + 1];
|
||||
ipRouteResult[ifname] = { src: src, default: false, gateway: null };
|
||||
});
|
||||
|
||||
// Parse default interfaces.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ('default' === tokens[0]) {
|
||||
let ifnameIndex = tokens.indexOf('dev');
|
||||
if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[ifnameIndex + 1];
|
||||
if (!ipRouteResult[ifname]) {
|
||||
return;
|
||||
}
|
||||
ipRouteResult[ifname].default = true;
|
||||
let gwIndex = tokens.indexOf('via');
|
||||
if (gwIndex < 0 || gwIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
ipRouteResult[ifname].gateway = tokens[gwIndex + 1];
|
||||
return;
|
||||
}
|
||||
});
|
||||
log("ip route result:" + JSON.stringify(ipRouteResult));
|
||||
|
||||
return ipRouteResult;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify everything about routing when the wifi tethering is either on or off.
|
||||
*
|
||||
@ -1044,87 +1172,8 @@ let gTestSuite = (function() {
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function verifyTetheringRouting(aEnabled) {
|
||||
let netcfgResult = {};
|
||||
let ipRouteResult = {};
|
||||
|
||||
// Execute 'netcfg' and parse to |netcfgResult|, each key of which is the
|
||||
// interface name and value is { ip(string) }.
|
||||
function exeAndParseNetcfg() {
|
||||
return runEmulatorShellSafe(['netcfg'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
|
||||
// eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
|
||||
// rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
|
||||
// rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
|
||||
// rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
|
||||
// wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
|
||||
// sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
|
||||
// rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
|
||||
//
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 5) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[0];
|
||||
let ip = (tokens[2].split('/'))[0];
|
||||
netcfgResult[ifname] = { ip: ip };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Execute 'ip route' and parse to |ipRouteResult|, each key of which is the
|
||||
// interface name and value is { src(string), default(boolean) }.
|
||||
function exeAndParseIpRoute() {
|
||||
return runEmulatorShellSafe(['ip', 'route'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// 10.0.2.4 via 10.0.2.2 dev rmnet0
|
||||
// 10.0.2.3 via 10.0.2.2 dev rmnet0
|
||||
// 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
|
||||
// 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
|
||||
// 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
|
||||
// default via 10.0.2.2 dev rmnet0
|
||||
// default via 10.0.2.2 dev eth0 metric 2
|
||||
//
|
||||
|
||||
// Parse source ip for each interface.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.trim().split(/\s+/);
|
||||
let srcIndex = tokens.indexOf('src');
|
||||
if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[2];
|
||||
let src = tokens[srcIndex + 1];
|
||||
ipRouteResult[ifname] = { src: src, default: false };
|
||||
});
|
||||
|
||||
// Parse default interfaces.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ('default' === tokens[0]) {
|
||||
let ifnameIndex = tokens.indexOf('dev');
|
||||
if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[ifnameIndex + 1];
|
||||
if (ipRouteResult[ifname]) {
|
||||
ipRouteResult[ifname].default = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
let netcfgResult;
|
||||
let ipRouteResult;
|
||||
|
||||
// Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
|
||||
// when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
|
||||
@ -1158,9 +1207,6 @@ let gTestSuite = (function() {
|
||||
}
|
||||
|
||||
function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
|
||||
log(JSON.stringify(ipRouteResult));
|
||||
log(JSON.stringify(netcfgResult));
|
||||
|
||||
if (aEnabled) {
|
||||
isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
|
||||
isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
|
||||
@ -1173,7 +1219,9 @@ let gTestSuite = (function() {
|
||||
|
||||
return verifyIptables()
|
||||
.then(exeAndParseNetcfg)
|
||||
.then((aResult) => { netcfgResult = aResult; })
|
||||
.then(exeAndParseIpRoute)
|
||||
.then((aResult) => { ipRouteResult = aResult; })
|
||||
.then(() => getSettings(SETTINGS_TETHERING_WIFI_IP))
|
||||
.then(ip => verifyDefaultRouteAndIp(ip));
|
||||
}
|
||||
@ -1244,6 +1292,7 @@ let gTestSuite = (function() {
|
||||
suite.getFirstIndexBySsid = getFirstIndexBySsid;
|
||||
suite.testAssociate = testAssociate;
|
||||
suite.getKnownNetworks = getKnownNetworks;
|
||||
suite.setStaticIpMode = setStaticIpMode;
|
||||
suite.requestWifiScan = requestWifiScan;
|
||||
suite.waitForConnected = waitForConnected;
|
||||
suite.forgetNetwork = forgetNetwork;
|
||||
@ -1254,6 +1303,8 @@ let gTestSuite = (function() {
|
||||
suite.getImportedCerts = getImportedCerts;
|
||||
suite.deleteCert = deleteCert;
|
||||
suite.writeFile = writeFile;
|
||||
suite.exeAndParseNetcfg = exeAndParseNetcfg;
|
||||
suite.exeAndParseIpRoute = exeAndParseIpRoute;
|
||||
|
||||
/**
|
||||
* Common test routine.
|
||||
|
@ -8,6 +8,7 @@ qemu = true
|
||||
[test_wifi_associate.js]
|
||||
[test_wifi_associate_wo_connect.js]
|
||||
[test_wifi_auto_connect.js]
|
||||
[test_wifi_static_ip.js]
|
||||
[test_wifi_tethering_wifi_disabled.js]
|
||||
[test_wifi_tethering_wifi_inactive.js]
|
||||
[test_wifi_tethering_wifi_active.js]
|
||||
|
41
dom/wifi/test/marionette/test_wifi_static_ip.js
Normal file
41
dom/wifi/test/marionette/test_wifi_static_ip.js
Normal file
@ -0,0 +1,41 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
const STATIC_IP_CONFIG = {
|
||||
enabled: true,
|
||||
ipaddr: "192.168.111.222",
|
||||
proxy: "",
|
||||
maskLength: 24,
|
||||
gateway: "192.168.111.1",
|
||||
dns1: "8.8.8.8",
|
||||
dns2: "8.8.4.4",
|
||||
};
|
||||
|
||||
function testAssociateWithStaticIp(aNetwork, aStaticIpConfig) {
|
||||
return gTestSuite.setStaticIpMode(aNetwork, aStaticIpConfig)
|
||||
.then(() => gTestSuite.testAssociate(aNetwork))
|
||||
// Check ip address and prefix.
|
||||
.then(() => gTestSuite.exeAndParseNetcfg())
|
||||
.then((aResult) => {
|
||||
is(aResult["wlan0"].ip, aStaticIpConfig.ipaddr, "Check ip address");
|
||||
is(aResult["wlan0"].prefix, aStaticIpConfig.maskLength, "Check prefix");
|
||||
})
|
||||
// Check routing.
|
||||
.then(() => gTestSuite.exeAndParseIpRoute())
|
||||
.then((aResult) => {
|
||||
is(aResult["wlan0"].src, aStaticIpConfig.ipaddr, "Check ip address");
|
||||
is(aResult["wlan0"].default, true, "Check default route");
|
||||
is(aResult["wlan0"].gateway, aStaticIpConfig.gateway, "Check gateway");
|
||||
});
|
||||
}
|
||||
|
||||
// Start test.
|
||||
gTestSuite.doTest(function() {
|
||||
return gTestSuite.ensureWifiEnabled(true)
|
||||
.then(() => gTestSuite.requestWifiScan())
|
||||
.then((aNetworks) => testAssociateWithStaticIp(aNetworks[0],
|
||||
STATIC_IP_CONFIG));
|
||||
});
|
@ -12,8 +12,6 @@
|
||||
#include <unistd.h>
|
||||
#include "mozilla/ipc/BluetoothDaemonConnectionConsumer.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketConnector.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
@ -201,35 +199,16 @@ BluetoothDaemonPDUConsumer::~BluetoothDaemonPDUConsumer()
|
||||
// BluetoothDaemonConnectionIO
|
||||
//
|
||||
|
||||
class BluetoothDaemonConnectionIO final
|
||||
: public UnixSocketWatcher
|
||||
, public ConnectionOrientedSocketIO
|
||||
class BluetoothDaemonConnectionIO final : public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer);
|
||||
|
||||
// Task callback methods
|
||||
//
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
void OnConnected() override;
|
||||
void OnError(const char* aFunction, int aErrno) override;
|
||||
|
||||
// Methods for |ConnectionOrientedSocketIO|
|
||||
//
|
||||
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) override;
|
||||
|
||||
// Methods for |DataSocketIO|
|
||||
//
|
||||
|
||||
@ -260,10 +239,14 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread,
|
||||
aIOLoop,
|
||||
aFd,
|
||||
aConnectionStatus,
|
||||
aConnector)
|
||||
, mConnection(aConnection)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
@ -272,98 +255,6 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
|
||||
MOZ_ASSERT(mConsumer);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
|
||||
EnqueueData(aBuffer);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
MOZ_ASSERT(!IsShutdownOnIOThread());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(SendPendingData(GetFd())))) {
|
||||
RemoveWatchers(WRITE_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
|
||||
// Clean up watchers, status, fd
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// |ConnectionOrientedSocketIO|
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonConnectionIO::Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
// File-descriptor setup
|
||||
|
||||
if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
|
||||
OnError("fcntl", errno);
|
||||
ScopedClose cleanupFd(aFd);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Signal success
|
||||
OnConnected();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// |DataSocketIO|
|
||||
|
||||
nsresult
|
||||
@ -464,16 +355,11 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
|
||||
{
|
||||
MOZ_ASSERT(!mIO);
|
||||
|
||||
// |BluetoothDaemonConnection| now owns the connector, but doesn't
|
||||
// actually use it. So the connector is stored in an auto pointer
|
||||
// to be deleted at the end of the method.
|
||||
nsAutoPtr<UnixSocketConnector> connector(aConnector);
|
||||
|
||||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
mIO = new BluetoothDaemonConnectionIO(
|
||||
aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
|
||||
this, mPDUConsumer);
|
||||
aConnector, this, mPDUConsumer);
|
||||
aIO = mIO;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ConnectionOrientedSocket.h"
|
||||
#include "UnixSocketConnector.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
@ -14,13 +15,172 @@ namespace ipc {
|
||||
//
|
||||
|
||||
ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
|
||||
nsIThread* aConsumerThread)
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector)
|
||||
: DataSocketIO(aConsumerThread)
|
||||
{ }
|
||||
, UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, mConnector(aConnector)
|
||||
, mPeerAddressLength(0)
|
||||
{
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
UnixSocketConnector* aConnector)
|
||||
: DataSocketIO(aConsumerThread)
|
||||
, UnixSocketWatcher(aIOLoop)
|
||||
, mConnector(aConnector)
|
||||
, mPeerAddressLength(0)
|
||||
{
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO()
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
ConnectionOrientedSocketIO::Accept(int aFd,
|
||||
const struct sockaddr* aPeerAddress,
|
||||
socklen_t aPeerAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Address setup
|
||||
mPeerAddressLength = aPeerAddressLength;
|
||||
memcpy(&mPeerAddress, aPeerAddress, mPeerAddressLength);
|
||||
|
||||
// Signal success and start data transfer
|
||||
OnConnected();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ConnectionOrientedSocketIO::Connect()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
|
||||
struct sockaddr* peerAddress =
|
||||
reinterpret_cast<struct sockaddr*>(&mPeerAddress);
|
||||
mPeerAddressLength = sizeof(mPeerAddress);
|
||||
|
||||
int fd;
|
||||
nsresult rv = mConnector->CreateStreamSocket(peerAddress,
|
||||
&mPeerAddressLength,
|
||||
fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SetFd(fd);
|
||||
|
||||
// calls OnConnected() on success, or OnError() otherwise
|
||||
rv = UnixSocketWatcher::Connect(peerAddress, mPeerAddressLength);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::Send(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
EnqueueData(aBuffer);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
// |UnixSocketWatcher|
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
MOZ_ASSERT(!IsShutdownOnIOThread());
|
||||
|
||||
nsresult rv = SendPendingData(GetFd());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnListening()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
NS_NOTREACHED("Invalid call to |ConnectionOrientedSocketIO::OnListening|");
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
|
||||
// Clean up watchers, status, fd
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
//
|
||||
// ConnectionOrientedSocket
|
||||
//
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include "DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
|
||||
class MessageLoop;
|
||||
|
||||
@ -23,15 +24,72 @@ class UnixSocketConnector;
|
||||
* |ListenSocket| uses these classes to handle accepted sockets.
|
||||
*/
|
||||
|
||||
class ConnectionOrientedSocketIO : public DataSocketIO
|
||||
class ConnectionOrientedSocketIO
|
||||
: public DataSocketIO
|
||||
, public UnixSocketWatcher
|
||||
{
|
||||
public:
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread);
|
||||
virtual ~ConnectionOrientedSocketIO();
|
||||
|
||||
virtual nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) = 0;
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength);
|
||||
|
||||
nsresult Connect();
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
// Methods for |UnixSocketWatcher|
|
||||
//
|
||||
|
||||
void OnSocketCanReceiveWithoutBlocking() final;
|
||||
void OnSocketCanSendWithoutBlocking() final;
|
||||
|
||||
void OnListening() final;
|
||||
void OnConnected() final;
|
||||
void OnError(const char* aFunction, int aErrno) final;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructs an instance of |ConnectionOrientedSocketIO|
|
||||
*
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O loop.
|
||||
* @param aFd The socket file descriptor.
|
||||
* @param aConnectionStatus The connection status for |aFd|.
|
||||
* @param aConnector Connector object for socket-type-specific methods.
|
||||
*/
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector);
|
||||
|
||||
/**
|
||||
* Constructs an instance of |ConnectionOrientedSocketIO|
|
||||
*
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O loop.
|
||||
* @param aConnector Connector object for socket-type-specific methods.
|
||||
*/
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
UnixSocketConnector* aConnector);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Connector object used to create the connection we are currently using.
|
||||
*/
|
||||
nsAutoPtr<UnixSocketConnector> mConnector;
|
||||
|
||||
/**
|
||||
* Number of valid bytes in |mPeerAddress|.
|
||||
*/
|
||||
socklen_t mPeerAddressLength;
|
||||
|
||||
/**
|
||||
* Address of the socket's current peer.
|
||||
*/
|
||||
struct sockaddr_storage mPeerAddress;
|
||||
};
|
||||
|
||||
class ConnectionOrientedSocket : public DataSocket
|
||||
|
@ -20,9 +20,7 @@ namespace ipc {
|
||||
// StreamSocketIO
|
||||
//
|
||||
|
||||
class StreamSocketIO final
|
||||
: public UnixSocketWatcher
|
||||
, public ConnectionOrientedSocketIO
|
||||
class StreamSocketIO final : public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
class ConnectTask;
|
||||
@ -50,32 +48,6 @@ public:
|
||||
void ClearDelayedConnectTask();
|
||||
void CancelDelayedConnectTask();
|
||||
|
||||
// Task callback methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Connect to a socket
|
||||
*/
|
||||
void Connect();
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
// I/O callback methods
|
||||
//
|
||||
|
||||
void OnConnected() override;
|
||||
void OnError(const char* aFunction, int aErrno) override;
|
||||
void OnListening() override;
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
// Methods for |ConnectionOrientedSocketIO|
|
||||
//
|
||||
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) override;
|
||||
|
||||
// Methods for |DataSocket|
|
||||
//
|
||||
|
||||
@ -95,8 +67,6 @@ public:
|
||||
void ShutdownOnIOThread() override;
|
||||
|
||||
private:
|
||||
void FireSocketError();
|
||||
|
||||
/**
|
||||
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
|
||||
* directly from consumer thread. All non-consumer-thread accesses should
|
||||
@ -104,26 +74,11 @@ private:
|
||||
*/
|
||||
RefPtr<StreamSocket> mStreamSocket;
|
||||
|
||||
/**
|
||||
* Connector object used to create the connection we are currently using.
|
||||
*/
|
||||
nsAutoPtr<UnixSocketConnector> mConnector;
|
||||
|
||||
/**
|
||||
* If true, do not requeue whatever task we're running
|
||||
*/
|
||||
bool mShuttingDownOnIOThread;
|
||||
|
||||
/**
|
||||
* Number of valid bytes in |mAddress|
|
||||
*/
|
||||
socklen_t mAddressLength;
|
||||
|
||||
/**
|
||||
* Address structure of the socket currently in use
|
||||
*/
|
||||
struct sockaddr_storage mAddress;
|
||||
|
||||
/**
|
||||
* Task member for delayed connect task. Should only be access on consumer
|
||||
* thread.
|
||||
@ -140,16 +95,12 @@ StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector)
|
||||
: UnixSocketWatcher(aIOLoop)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread, aIOLoop, aConnector)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddressLength(0)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
@ -157,16 +108,16 @@ StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread,
|
||||
aIOLoop,
|
||||
aFd,
|
||||
aConnectionStatus,
|
||||
aConnector)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddressLength(0)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
StreamSocketIO::~StreamSocketIO()
|
||||
@ -216,145 +167,6 @@ StreamSocketIO::CancelDelayedConnectTask()
|
||||
ClearDelayedConnectTask();
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::Connect()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(mConnector);
|
||||
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
|
||||
struct sockaddr* address = reinterpret_cast<struct sockaddr*>(&mAddress);
|
||||
mAddressLength = sizeof(mAddress);
|
||||
|
||||
int fd;
|
||||
nsresult rv = mConnector->CreateStreamSocket(address, &mAddressLength, fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
FireSocketError();
|
||||
return;
|
||||
}
|
||||
SetFd(fd);
|
||||
|
||||
// calls OnConnected() on success, or OnError() otherwise
|
||||
rv = UnixSocketWatcher::Connect(address, mAddressLength);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::Send(UnixSocketIOBuffer* aData)
|
||||
{
|
||||
EnqueueData(aData);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnListening()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
NS_NOTREACHED("Invalid call to |StreamSocketIO::OnListening|");
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
FireSocketError();
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
nsresult rv = SendPendingData(GetFd());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::FireSocketError()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
// Clean up watchers, statuses, fds
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// |ConnectionOrientedSocketIO|
|
||||
|
||||
nsresult
|
||||
StreamSocketIO::Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Address setup
|
||||
mAddressLength = aAddressLength;
|
||||
memcpy(&mAddress, aAddress, mAddressLength);
|
||||
|
||||
// Signal success
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// |DataSocketIO|
|
||||
|
||||
nsresult
|
||||
|
@ -3,6 +3,9 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# This file is included at the top of all native android mozconfigs
|
||||
if [ "x$IS_NIGHTLY" = "xyes" ]; then
|
||||
MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
|
||||
fi
|
||||
|
||||
MOZ_AUTOMATION_L10N_CHECK=0
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
@ -214,6 +214,7 @@
|
||||
@BINPATH@/components/necko_file.xpt
|
||||
@BINPATH@/components/necko_ftp.xpt
|
||||
@BINPATH@/components/necko_http.xpt
|
||||
@BINPATH@/components/necko_mdns.xpt
|
||||
@BINPATH@/components/necko_res.xpt
|
||||
@BINPATH@/components/necko_socket.xpt
|
||||
@BINPATH@/components/necko_strconv.xpt
|
||||
|
665
netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
Normal file
665
netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
Normal file
@ -0,0 +1,665 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
#include "nsASocketHandler.h"
|
||||
|
||||
inline PRLogModuleInfo*
|
||||
GetOperatorLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MDNSResponderOperator");
|
||||
return log;
|
||||
}
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) PR_LOG(GetOperatorLog(), PR_LOG_NOTICE, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) PR_LOG(GetOperatorLog(), PR_LOG_ERROR, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator::ServiceWatcher final
|
||||
: public nsASocketHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsASocketHandler methods
|
||||
virtual void OnSocketReady(PRFileDesc* fd, int16_t outFlags) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL)) {
|
||||
LOG_E("error polling on listening socket (%p)", fd);
|
||||
mCondition = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!(outFlags & PR_POLL_READ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DNSServiceProcessResult(mService);
|
||||
}
|
||||
|
||||
virtual void OnSocketDetached(PRFileDesc *fd) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (!mFD) {
|
||||
return;
|
||||
}
|
||||
|
||||
PR_Close(mFD);
|
||||
mFD = nullptr;
|
||||
}
|
||||
|
||||
virtual void IsLocal(bool *aIsLocal) override { *aIsLocal = true; }
|
||||
|
||||
virtual void KeepWhenOffline(bool *aKeepWhenOffline) override
|
||||
{
|
||||
*aKeepWhenOffline = true;
|
||||
}
|
||||
|
||||
virtual uint64_t ByteCountSent() override { return 0; }
|
||||
virtual uint64_t ByteCountReceived() override { return 0; }
|
||||
|
||||
explicit ServiceWatcher(DNSServiceRef aService)
|
||||
: mSts(nullptr)
|
||||
, mService(aService)
|
||||
, mFD(nullptr)
|
||||
, mAttached(false)
|
||||
{
|
||||
if (!gSocketTransportService)
|
||||
{
|
||||
nsCOMPtr<nsISocketTransportService> sts =
|
||||
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Init()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (!mService) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mSts = gSocketTransportService;
|
||||
|
||||
int osfd = DNSServiceRefSockFD(mService);
|
||||
if (osfd == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFD = PR_ImportFile(osfd);
|
||||
return PostEvent(&ServiceWatcher::OnMsgAttach);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (mService) {
|
||||
DNSServiceRefDeallocate(mService);
|
||||
mService = nullptr;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return;
|
||||
}
|
||||
|
||||
PostEvent(&ServiceWatcher::OnMsgClose);
|
||||
}
|
||||
|
||||
private:
|
||||
~ServiceWatcher() = default;
|
||||
|
||||
nsresult PostEvent(void(ServiceWatcher::*func)(void))
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, func);
|
||||
return gSocketTransportService->Dispatch(ev, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void OnMsgClose()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// tear down socket. this signals the STS to detach our socket handler.
|
||||
mCondition = NS_BINDING_ABORTED;
|
||||
|
||||
// if we are attached, then socket transport service will call our
|
||||
// OnSocketDetached method automatically. Otherwise, we have to call it
|
||||
// (and thus close the socket) manually.
|
||||
if (!mAttached) {
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
}
|
||||
|
||||
void OnMsgAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCondition = TryAttach();
|
||||
|
||||
// if we hit an error while trying to attach then bail...
|
||||
if (NS_FAILED(mCondition)) {
|
||||
NS_ASSERTION(!mAttached, "should not be attached already");
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsresult TryAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//
|
||||
// find out if it is going to be ok to attach another socket to the STS.
|
||||
// if not then we have to wait for the STS to tell us that it is ok.
|
||||
// the notification is asynchronous, which means that when we could be
|
||||
// in a race to call AttachSocket once notified. for this reason, when
|
||||
// we get notified, we just re-enter this function. as a result, we are
|
||||
// sure to ask again before calling AttachSocket. in this way we deal
|
||||
// with the race condition. though it isn't the most elegant solution,
|
||||
// it is far simpler than trying to build a system that would guarantee
|
||||
// FIFO ordering (which wouldn't even be that valuable IMO). see bug
|
||||
// 194402 for more info.
|
||||
//
|
||||
if (!gSocketTransportService->CanAttachSocket()) {
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &ServiceWatcher::OnMsgAttach);
|
||||
|
||||
nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ok, we can now attach our socket to the STS for polling
|
||||
//
|
||||
rv = gSocketTransportService->AttachSocket(mFD, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mAttached = true;
|
||||
|
||||
//
|
||||
// now, configure our poll flags for listening...
|
||||
//
|
||||
mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsSocketTransportService> mSts;
|
||||
DNSServiceRef mService;
|
||||
PRFileDesc* mFD;
|
||||
bool mAttached;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MDNSResponderOperator::ServiceWatcher, nsISupports)
|
||||
|
||||
MDNSResponderOperator::MDNSResponderOperator()
|
||||
: mService(nullptr)
|
||||
, mWatcher(nullptr)
|
||||
, mThread(NS_GetCurrentThread())
|
||||
, mIsCancelled(false)
|
||||
{
|
||||
}
|
||||
|
||||
MDNSResponderOperator::~MDNSResponderOperator()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Start()
|
||||
{
|
||||
if (mIsCancelled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsServing()) {
|
||||
Stop();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Stop()
|
||||
{
|
||||
mThread = nullptr;
|
||||
return ResetService(nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::ResetService(DNSServiceRef aService)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aService != mService) {
|
||||
if (mWatcher) {
|
||||
mWatcher->Close();
|
||||
mWatcher = nullptr;
|
||||
}
|
||||
|
||||
if (aService) {
|
||||
nsRefPtr<ServiceWatcher> watcher = new ServiceWatcher(aService);
|
||||
if (NS_WARN_IF(NS_FAILED(watcher->Init()))) {
|
||||
return rv;
|
||||
}
|
||||
mWatcher = watcher;
|
||||
}
|
||||
|
||||
mService = aService;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BrowseOperator::BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceType(aServiceType)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err = DNSServiceBrowse(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
mServiceType.get(),
|
||||
nullptr,
|
||||
&BrowseReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
if (mListener) {
|
||||
if (kDNSServiceErr_NoError == err) {
|
||||
mListener->OnDiscoveryStarted(mServiceType);
|
||||
} else {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, err);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnDiscoveryStopped(mServiceType);
|
||||
} else {
|
||||
mListener->OnStopDiscoveryFailed(mServiceType,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("BrowseOperator::Reply (%d)", aErrorCode);
|
||||
if (mListener) {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, aErrorCode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo();
|
||||
|
||||
if (NS_WARN_IF(!info)) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aServiceName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aReplyDomain)))) { return; }
|
||||
|
||||
if (aFlags & kDNSServiceFlagsAdd) {
|
||||
mListener->OnServiceFound(info);
|
||||
} else {
|
||||
mListener->OnServiceLost(info);
|
||||
}
|
||||
}
|
||||
|
||||
RegisterOperator::RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MDNSResponderOperator::Start();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
uint16_t port;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoCString type;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetServiceType(type)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
TXTRecordRef txtRecord;
|
||||
char buf[TXT_BUFFER_SIZE] = { 0 };
|
||||
TXTRecordCreate(&txtRecord, TXT_BUFFER_SIZE, buf);
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes;
|
||||
if (NS_FAILED(rv = mServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
LOG_I("register: no attributes");
|
||||
} else {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(rv =
|
||||
attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetName(name)));
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetValue(getter_AddRefs(value))));
|
||||
|
||||
nsAutoCString str;
|
||||
if (NS_WARN_IF(NS_FAILED(value->GetAsACString(str)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TXTRecordSetValue(&txtRecord,
|
||||
/* it's safe because key name is ASCII only. */
|
||||
NS_LossyConvertUTF16toASCII(name).get(),
|
||||
str.Length(),
|
||||
str.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
nsAutoCString name;
|
||||
nsAutoCString domain;
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceRegister(&service,
|
||||
0,
|
||||
0,
|
||||
NS_SUCCEEDED(mServiceInfo->GetServiceName(name)) ?
|
||||
name.get() : nullptr,
|
||||
type.get(),
|
||||
NS_SUCCEEDED(mServiceInfo->GetDomainName(domain)) ?
|
||||
domain.get() : nullptr,
|
||||
NS_SUCCEEDED(mServiceInfo->GetHost(host)) ?
|
||||
host.get() : nullptr,
|
||||
NativeEndian::swapToNetworkOrder(port),
|
||||
TXTRecordGetLength(&txtRecord),
|
||||
TXTRecordGetBytesPtr(&txtRecord),
|
||||
&RegisterReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
TXTRecordDeallocate(&txtRecord);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnRegistrationFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnServiceUnregistered(mServiceInfo);
|
||||
} else {
|
||||
mListener->OnUnregistrationFailed(mServiceInfo,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (kDNSServiceErr_NoError != aErrorCode) {
|
||||
LOG_E("RegisterOperator::Reply (%d)", aErrorCode);
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aDomain)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceRegistered(info);
|
||||
} else {
|
||||
mListener->OnRegistrationFailed(info, aErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveOperator::ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
, mDeleteProtector()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString name;
|
||||
mServiceInfo->GetServiceName(name);
|
||||
nsAutoCString type;
|
||||
mServiceInfo->GetServiceType(type);
|
||||
nsAutoCString domain;
|
||||
mServiceInfo->GetDomainName(domain);
|
||||
|
||||
LOG_I("Resolve: (%s), (%s), (%s)", name.get(), type.get(), domain.get());
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceResolve(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
name.get(),
|
||||
type.get(),
|
||||
domain.get(),
|
||||
(DNSServiceResolveReply)&ResolveReplyRunnable::Reply,
|
||||
this);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnResolveFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mDeleteProtector = this;
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Stop()
|
||||
{
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
mDeleteProtector = nullptr;
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("ResolveOperator::Reply (%d)", aErrorCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve TXT record
|
||||
int count = TXTRecordGetCount(aTxtLen, aTxtRecord);
|
||||
LOG_I("resolve: txt count = %d, len = %d", count, aTxtLen);
|
||||
nsCOMPtr<nsIWritablePropertyBag2> attributes = nullptr;
|
||||
if (count) {
|
||||
attributes = new nsHashPropertyBag();
|
||||
if (NS_WARN_IF(!attributes)) { return; }
|
||||
for (int i = 0; i < count; ++i) {
|
||||
char key[TXT_BUFFER_SIZE] = { '\0' };
|
||||
uint8_t vSize = 0;
|
||||
const void* value = nullptr;
|
||||
if (kDNSServiceErr_NoError !=
|
||||
TXTRecordGetItemAtIndex(aTxtLen,
|
||||
aTxtRecord,
|
||||
i,
|
||||
TXT_BUFFER_SIZE,
|
||||
key,
|
||||
&vSize,
|
||||
&value)) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString str(reinterpret_cast<const char*>(value), vSize);
|
||||
LOG_I("resolve TXT: (%d) %s=%s", vSize, key, str.get());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->SetPropertyAsACString(
|
||||
/* it's safe to convert because key name is ASCII only. */
|
||||
NS_ConvertASCIItoUTF16(key),
|
||||
str)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetHost(aHostTarget)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetPort(aPort)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetAttributes(attributes)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceResolved(info);
|
||||
} else {
|
||||
mListener->OnResolveFailed(info, aErrorCode);
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(Stop()));
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
139
netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
Normal file
139
netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
MDNSResponderOperator();
|
||||
|
||||
virtual nsresult Start();
|
||||
virtual nsresult Stop();
|
||||
void Cancel() { mIsCancelled = true; }
|
||||
nsIThread* GetThread() const { return mThread; }
|
||||
|
||||
protected:
|
||||
virtual ~MDNSResponderOperator();
|
||||
|
||||
bool IsServing() const { return mService; }
|
||||
nsresult ResetService(DNSServiceRef aService);
|
||||
|
||||
private:
|
||||
class ServiceWatcher;
|
||||
|
||||
DNSServiceRef mService;
|
||||
nsRefPtr<ServiceWatcher> mWatcher;
|
||||
nsCOMPtr<nsIThread> mThread; // remember caller thread for callback
|
||||
Atomic<bool> mIsCancelled;
|
||||
};
|
||||
|
||||
class BrowseOperator final : private MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BrowseOperator)
|
||||
|
||||
BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain);
|
||||
|
||||
private:
|
||||
~BrowseOperator() = default;
|
||||
|
||||
nsCString mServiceType;
|
||||
nsCOMPtr<nsIDNSServiceDiscoveryListener> mListener;
|
||||
};
|
||||
|
||||
class RegisterOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RegisterOperator)
|
||||
|
||||
RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain);
|
||||
|
||||
private:
|
||||
~RegisterOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSRegistrationListener> mListener;
|
||||
};
|
||||
|
||||
class ResolveOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResolveOperator)
|
||||
|
||||
ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord);
|
||||
|
||||
private:
|
||||
~ResolveOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSServiceResolveListener> mListener;
|
||||
|
||||
// hold self until callback is made.
|
||||
nsRefPtr<ResolveOperator> mDeleteProtector;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
225
netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
Normal file
225
netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
BrowseReplyRunnable::BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mServiceName(aServiceName)
|
||||
, mRegType(aRegType)
|
||||
, mReplyDomain(aReplyDomain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BrowseReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mServiceName,
|
||||
mRegType,
|
||||
mReplyDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
BrowseOperator* obj(reinterpret_cast<BrowseOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new BrowseReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aServiceName),
|
||||
nsCString(aRegType),
|
||||
nsCString(aReplyDomain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
RegisterReplyRunnable::RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& domain,
|
||||
RegisterOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mName(aName)
|
||||
, mRegType(aRegType)
|
||||
, mDomain(domain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mErrorCode,
|
||||
mName,
|
||||
mRegType,
|
||||
mDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* domain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
RegisterOperator* obj(reinterpret_cast<RegisterOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new RegisterReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aErrorCode,
|
||||
nsCString(aName),
|
||||
nsCString(aRegType),
|
||||
nsCString(domain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mFullname(aFullName)
|
||||
, mHosttarget(aHostTarget)
|
||||
, mPort(aPort)
|
||||
, mTxtLen(aTxtLen)
|
||||
, mTxtRecord(new unsigned char[aTxtLen])
|
||||
, mContext(aContext)
|
||||
{
|
||||
if (mTxtRecord) {
|
||||
memcpy(mTxtRecord.get(), aTxtRecord, aTxtLen);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::~ResolveReplyRunnable()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ResolveReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mFullname,
|
||||
mHosttarget,
|
||||
mPort,
|
||||
mTxtLen,
|
||||
mTxtRecord.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
ResolveOperator* obj(reinterpret_cast<ResolveOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new ResolveReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aFullName),
|
||||
nsCString(aHostTarget),
|
||||
NativeEndian::swapFromNetworkOrder(aPort),
|
||||
aTxtLen,
|
||||
aTxtRecord,
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
128
netwerk/dns/mdns/libmdns/MDNSResponderReply.h
Normal file
128
netwerk/dns/mdns/libmdns/MDNSResponderReply.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mServiceName;
|
||||
nsCString mRegType;
|
||||
nsCString mReplyDomain;
|
||||
BrowseOperator* mContext;
|
||||
};
|
||||
|
||||
class RegisterReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain,
|
||||
RegisterOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* aDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mName;
|
||||
nsCString mRegType;
|
||||
nsCString mDomain;
|
||||
RegisterOperator* mContext;
|
||||
};
|
||||
|
||||
class ResolveReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext);
|
||||
~ResolveReplyRunnable();
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mFullname;
|
||||
nsCString mHosttarget;
|
||||
uint16_t mPort;
|
||||
uint16_t mTxtLen;
|
||||
UniquePtr<unsigned char> mTxtRecord;
|
||||
nsRefPtr<ResolveOperator> mContext;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
33
netwerk/dns/mdns/libmdns/moz.build
Normal file
33
netwerk/dns/mdns/libmdns/moz.build
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] >= '16':
|
||||
UNIFIED_SOURCES += [
|
||||
'MDNSResponderOperator.cpp',
|
||||
'MDNSResponderReply.cpp',
|
||||
'nsDNSServiceDiscovery.cpp',
|
||||
]
|
||||
|
||||
CXXFLAGS += [
|
||||
'-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
|
||||
'external/mdnsresponder/mDNSShared',
|
||||
]
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/netwerk/base',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDNSServiceInfo.cpp',
|
||||
'nsMulticastDNSModule.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
230
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
Normal file
230
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#include <cutils/properties.h>
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
StartService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "running") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.start", "mdnsd");
|
||||
}
|
||||
|
||||
void
|
||||
StopService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "stopped") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.stop", "mdnsd");
|
||||
}
|
||||
|
||||
class DiscoveryRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~DiscoveryRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSServiceDiscoveryListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(DiscoveryRequest, nsICancelable)
|
||||
|
||||
DiscoveryRequest::DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DiscoveryRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->StopDiscovery(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class RegisterRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~RegisterRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSRegistrationListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RegisterRequest, nsICancelable)
|
||||
|
||||
RegisterRequest::RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->UnregisterService(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceDiscovery, nsIDNSServiceDiscovery)
|
||||
|
||||
nsresult
|
||||
nsDNSServiceDiscovery::Init()
|
||||
{
|
||||
StartService();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StartDiscovery(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = StopDiscovery(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp = new BrowseOperator(aServiceType,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Put(aListener, browserOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StopDiscovery(nsIDNSServiceDiscoveryListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp;
|
||||
if (!mDiscoveryMap.Get(aListener, getter_AddRefs(browserOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
browserOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::RegisterService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = UnregisterService(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp = new RegisterOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Put(aListener, registerOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::UnregisterService(nsIDNSRegistrationListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp;
|
||||
if (!mRegisterMap.Get(aListener, getter_AddRefs(registerOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
registerOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::ResolveService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<ResolveOperator> resolveOp = new ResolveOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = resolveOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
48
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
Normal file
48
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseOperator;
|
||||
class RegisterOperator;
|
||||
|
||||
class nsDNSServiceDiscovery final : public nsIDNSServiceDiscovery
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEDISCOVERY
|
||||
|
||||
explicit nsDNSServiceDiscovery() = default;
|
||||
|
||||
/*
|
||||
** The mDNS service is started in this function. However, the function returns
|
||||
** without waiting. Therefore, all operations before service started will fail
|
||||
** and get error code |kDNSServiceErr_ServiceNotRunning| defined in dns_sd.h.
|
||||
**/
|
||||
nsresult Init();
|
||||
|
||||
nsresult StopDiscovery(nsIDNSServiceDiscoveryListener* aListener);
|
||||
nsresult UnregisterService(nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceDiscovery() = default;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, BrowseOperator> mDiscoveryMap;
|
||||
nsRefPtrHashtable<nsISupportsHashKey, RegisterOperator> mRegisterMap;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
183
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
Normal file
183
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceInfo, nsIDNSServiceInfo)
|
||||
|
||||
nsDNSServiceInfo::nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
uint16_t value;
|
||||
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetHost(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetHost(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetPort(&value))) {
|
||||
NS_WARN_IF(NS_FAILED(SetPort(value)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceName(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceType(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceType(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetDomainName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetDomainName(str)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes; // deep copy
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWritablePropertyBag2> newAttributes = new nsHashPropertyBag();
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
NS_WARN_IF(NS_FAILED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
NS_WARN_IF(NS_FAILED(property->GetName(name)));
|
||||
NS_WARN_IF(NS_FAILED(property->GetValue(getter_AddRefs(value))));
|
||||
NS_WARN_IF(NS_FAILED(newAttributes->SetPropertyAsInterface(name, value)));
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(SetAttributes(newAttributes)));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetHost(nsACString& aHost)
|
||||
{
|
||||
if (!mIsHostSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aHost = mHost;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetHost(const nsACString& aHost)
|
||||
{
|
||||
mHost = aHost;
|
||||
mIsHostSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetPort(uint16_t* aPort)
|
||||
{
|
||||
if (NS_WARN_IF(!aPort)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (!mIsPortSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
*aPort = mPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetPort(uint16_t aPort)
|
||||
{
|
||||
mPort = aPort;
|
||||
mIsPortSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceName(nsACString& aServiceName)
|
||||
{
|
||||
if (!mIsServiceNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceName = mServiceName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceName(const nsACString& aServiceName)
|
||||
{
|
||||
mServiceName = aServiceName;
|
||||
mIsServiceNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceType(nsACString& aServiceType)
|
||||
{
|
||||
if (!mIsServiceTypeSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceType = mServiceType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceType(const nsACString& aServiceType)
|
||||
{
|
||||
mServiceType = aServiceType;
|
||||
mIsServiceTypeSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetDomainName(nsACString& aDomainName)
|
||||
{
|
||||
if (!mIsDomainNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aDomainName = mDomainName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetDomainName(const nsACString& aDomainName)
|
||||
{
|
||||
mDomainName = aDomainName;
|
||||
mIsDomainNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetAttributes(nsIPropertyBag2** aAttributes)
|
||||
{
|
||||
if (!mIsAttributesSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPropertyBag2> attributes(mAttributes);
|
||||
attributes.forget(aAttributes);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetAttributes(nsIPropertyBag2* aAttributes)
|
||||
{
|
||||
mAttributes = aAttributes;
|
||||
mIsAttributesSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
48
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
Normal file
48
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class nsDNSServiceInfo final : public nsIDNSServiceInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEINFO
|
||||
|
||||
explicit nsDNSServiceInfo() = default;
|
||||
explicit nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceInfo() = default;
|
||||
|
||||
private:
|
||||
nsCString mHost;
|
||||
uint16_t mPort = 0;
|
||||
nsCString mServiceName;
|
||||
nsCString mServiceType;
|
||||
nsCString mDomainName;
|
||||
nsCOMPtr<nsIPropertyBag2> mAttributes;
|
||||
|
||||
bool mIsHostSet = false;
|
||||
bool mIsPortSet = false;
|
||||
bool mIsServiceNameSet = false;
|
||||
bool mIsServiceTypeSet = false;
|
||||
bool mIsDomainNameSet = false;
|
||||
bool mIsAttributesSet = false;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
61
netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
Normal file
61
netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16
|
||||
#define ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#endif
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#endif
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
using mozilla::net::nsDNSServiceDiscovery;
|
||||
#define DNSSERVICEDISCOVERY_CID \
|
||||
{0x8df43d23, 0xd3f9, 0x4dd5, \
|
||||
{ 0xb9, 0x65, 0xde, 0x2c, 0xa3, 0xf6, 0xa4, 0x2c }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSServiceDiscovery, Init)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEDISCOVERY_CID);
|
||||
#endif // ENABLE_DNS_SERVICE_DISCOVERY
|
||||
|
||||
using mozilla::net::nsDNSServiceInfo;
|
||||
#define DNSSERVICEINFO_CID \
|
||||
{0x14a50f2b, 0x7ff6, 0x48a5, \
|
||||
{ 0x88, 0xe3, 0x61, 0x5f, 0xd1, 0x11, 0xf5, 0xd3 }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDNSServiceInfo)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEINFO_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry knsDNSServiceDiscoveryCIDs[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ &kDNSSERVICEDISCOVERY_CID, false, nullptr, nsDNSServiceDiscoveryConstructor },
|
||||
#endif
|
||||
{ &kDNSSERVICEINFO_CID, false, nullptr, nsDNSServiceInfoConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry knsDNSServiceDiscoveryContracts[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ DNSSERVICEDISCOVERY_CONTRACT_ID, &kDNSSERVICEDISCOVERY_CID },
|
||||
#endif
|
||||
{ DNSSERVICEINFO_CONTRACT_ID, &kDNSSERVICEINFO_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry knsDNSServiceDiscoveryCategories[] = {
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module knsDNSServiceDiscoveryModule = {
|
||||
mozilla::Module::kVersion,
|
||||
knsDNSServiceDiscoveryCIDs,
|
||||
knsDNSServiceDiscoveryContracts,
|
||||
knsDNSServiceDiscoveryCategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(nsDNSServiceDiscoveryModule) = &knsDNSServiceDiscoveryModule;
|
13
netwerk/dns/mdns/moz.build
Normal file
13
netwerk/dns/mdns/moz.build
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DIRS += ['libmdns']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSServiceDiscovery.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_mdns'
|
213
netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
Normal file
213
netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
Normal file
@ -0,0 +1,213 @@
|
||||
/* 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 nsICancelable;
|
||||
interface nsIPropertyBag2;
|
||||
|
||||
/**
|
||||
* Service information
|
||||
*/
|
||||
[scriptable, uuid(112bfa89-1b57-4acf-8287-48e5466c1b39)]
|
||||
interface nsIDNSServiceInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
* The host name of the service. (E.g. "Android.local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String host;
|
||||
|
||||
/**
|
||||
* The port number of the service. (E.g. 80)
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute unsigned short port;
|
||||
|
||||
/**
|
||||
* The service name of the service for display. (E.g. "My TV")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceName;
|
||||
|
||||
/**
|
||||
* The type of the service. (E.g. "_http._tcp")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceType;
|
||||
|
||||
/**
|
||||
* The domain name of the service. (E.g. "local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String domainName;
|
||||
|
||||
/**
|
||||
* The attributes of the service.
|
||||
*/
|
||||
attribute nsIPropertyBag2 attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service discovery
|
||||
*/
|
||||
[scriptable, uuid(3025b7f2-97bb-435b-b43d-26731b3f5fc4)]
|
||||
interface nsIDNSServiceDiscoveryListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the discovery begins.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStarted(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the discovery ends.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStopped(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the a service is found.
|
||||
* @param aServiceInfo
|
||||
* the info about the found service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceFound(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the a service is lost.
|
||||
* @param aServiceInfo
|
||||
* the info about the lost service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceLost(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot start.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStartDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot stop.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStopDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service registration
|
||||
*/
|
||||
[scriptable, uuid(e165e4be-abf4-4963-a66d-ed3ca116e5e4)]
|
||||
interface nsIDNSRegistrationListener : nsISupports
|
||||
{
|
||||
const long ERROR_SERVICE_NOT_RUNNING = -65563;
|
||||
|
||||
/**
|
||||
* Callback when the service is registered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service,
|
||||
* where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceRegistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service is unregistered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the unregistered service.
|
||||
*/
|
||||
void onServiceUnregistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be registered.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be registered.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onRegistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be unregistered.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onUnregistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service resolve
|
||||
*/
|
||||
[scriptable, uuid(24ee6408-648e-421d-accf-c6e5adeccf97)]
|
||||
interface nsIDNSServiceResolveListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the service is resolved successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the resolved service, where |host| and |port| are set.
|
||||
*/
|
||||
void onServiceResolved(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be resolved.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be resolved.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onResolveFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The interface for DNS service discovery/registration/resolve
|
||||
*/
|
||||
[scriptable, uuid(6487899b-beb1-455a-ba65-e4fd465066d7)]
|
||||
interface nsIDNSServiceDiscovery : nsISupports
|
||||
{
|
||||
/**
|
||||
* Browse for instances of a service.
|
||||
* @param aServiceType
|
||||
* the service type to be discovered, E.g. "_http._tcp".
|
||||
* @param aListener
|
||||
* callback interface for discovery notifications.
|
||||
* @return An object that can be used to cancel the service discovery.
|
||||
*/
|
||||
nsICancelable startDiscovery(in AUTF8String aServiceType, in nsIDNSServiceDiscoveryListener aListener);
|
||||
|
||||
/**
|
||||
* Register a service that is discovered via |startDiscovery| and |resolveService| calls.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |port| and |aServiceType| are required attributes.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
* @return An object that can be used to cancel the service registration.
|
||||
*/
|
||||
nsICancelable registerService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSRegistrationListener aListener);
|
||||
|
||||
/**
|
||||
* Resolve a service name discovered via |startDiscovery| to a target host name, port number.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |serviceName|, |aServiceType|, and |domainName| are required attributes as reported to the |onServiceFound| callback.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
*/
|
||||
void resolveService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSServiceResolveListener aListener);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define DNSSERVICEDISCOVERY_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1"
|
||||
#define DNSSERVICEINFO_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-info;1"
|
||||
%}
|
@ -4,6 +4,10 @@
|
||||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'mdns',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSListener.idl',
|
||||
'nsIDNSRecord.idl',
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"repo": "https://hg.mozilla.org/build/mozharness",
|
||||
"revision": "476752fc4ea8"
|
||||
"revision": "3e36eedc67a2"
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ class DecisionTask(object):
|
||||
'owner': params['owner'],
|
||||
'as_slugid': SlugidJar(),
|
||||
'from_now': json_time_from_now,
|
||||
'now': datetime.datetime.now().isoformat()
|
||||
'now': current_json_time()
|
||||
}.items())
|
||||
task = templates.load(params['task'], parameters)
|
||||
print(json.dumps(task, indent=4))
|
||||
@ -225,7 +225,7 @@ class Graph(object):
|
||||
'head_rev': params['head_rev'],
|
||||
'owner': params['owner'],
|
||||
'from_now': json_time_from_now,
|
||||
'now': datetime.datetime.now().isoformat(),
|
||||
'now': current_json_time(),
|
||||
'mozharness_repository': mozharness['repo'],
|
||||
'mozharness_rev': mozharness['revision'],
|
||||
'mozharness_ref':mozharness.get('reference', mozharness['revision']),
|
||||
|
@ -29,6 +29,7 @@ XPCOMUtils.defineLazyGetter(this, "debuggerServer", () => {
|
||||
let debuggerServer = serverLoader.DebuggerServer;
|
||||
debuggerServer.init();
|
||||
debuggerServer.addBrowserActors();
|
||||
debuggerServer.allowChromeProcess = !l10n.hiddenByChromePref();
|
||||
return debuggerServer;
|
||||
});
|
||||
|
||||
|
@ -22,7 +22,7 @@ var Cu = require('chrome').Cu;
|
||||
|
||||
var prefSvc = Cc['@mozilla.org/preferences-service;1']
|
||||
.getService(Ci.nsIPrefService);
|
||||
var prefBranch = prefSvc.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
|
||||
var prefBranch = prefSvc.getBranch(null).QueryInterface(Ci.nsIPrefBranch);
|
||||
|
||||
var Services = Cu.import('resource://gre/modules/Services.jsm', {}).Services;
|
||||
var stringBundle = Services.strings.createBundle(
|
||||
@ -75,5 +75,5 @@ exports.lookupFormat = function(name, swaps) {
|
||||
* </pre>
|
||||
*/
|
||||
exports.hiddenByChromePref = function() {
|
||||
return !prefBranch.prefHasUserValue('devtools.chrome.enabled');
|
||||
return !prefBranch.getBoolPref('devtools.chrome.enabled');
|
||||
};
|
||||
|
@ -258,6 +258,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
'sync',
|
||||
]
|
||||
|
||||
if CONFIG['ANDROID_VERSION'] >= '16':
|
||||
OS_LIBS += [
|
||||
'mdnssd',
|
||||
]
|
||||
|
||||
if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
|
||||
OS_LIBS += [
|
||||
'stagefright_foundation',
|
||||
|
@ -83,3 +83,8 @@ notification[type="critical"] {
|
||||
.popup-notification-button-container {
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.popup-notification-closebutton {
|
||||
-moz-margin-end: -10px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
@ -50,15 +50,23 @@ def MergeProfiles(files):
|
||||
pidStr = pid + ":"
|
||||
|
||||
thread['startTime'] = fileData['profileJSON']['meta']['startTime']
|
||||
samples = thread['samples']
|
||||
for sample in thread['samples']:
|
||||
for frame in sample['frames']:
|
||||
if "location" in frame and frame['location'][0:2] == '0x':
|
||||
oldLoc = frame['location']
|
||||
newLoc = pidStr + oldLoc
|
||||
frame['location'] = newLoc
|
||||
# Default to the unprefixed symbol if no translation is available
|
||||
symTable[newLoc] = oldLoc
|
||||
if meta['version'] >= 3:
|
||||
stringTable = thread['stringTable']
|
||||
for i, str in enumerate(stringTable):
|
||||
if str[:2] == '0x':
|
||||
newLoc = pidStr + str
|
||||
stringTable[i] = newLoc
|
||||
symTable[newLoc] = str
|
||||
else:
|
||||
samples = thread['samples']
|
||||
for sample in thread['samples']:
|
||||
for frame in sample['frames']:
|
||||
if "location" in frame and frame['location'][0:2] == '0x':
|
||||
oldLoc = frame['location']
|
||||
newLoc = pidStr + oldLoc
|
||||
frame['location'] = newLoc
|
||||
# Default to the unprefixed symbol if no translation is
|
||||
symTable[newLoc] = oldLoc
|
||||
|
||||
filesyms = fileData['symbolicationTable']
|
||||
for sym in filesyms.keys():
|
||||
@ -68,11 +76,19 @@ def MergeProfiles(files):
|
||||
# earliest start
|
||||
for thread in threads:
|
||||
delta = thread['startTime'] - minStartTime
|
||||
for sample in thread['samples']:
|
||||
if "time" in sample:
|
||||
sample['time'] += delta
|
||||
for marker in thread['markers']:
|
||||
marker['time'] += delta
|
||||
if meta['version'] >= 3:
|
||||
idxTime = thread['samples']['schema']['time']
|
||||
for sample in thread['samples']['data']:
|
||||
sample[idxTime] += delta
|
||||
idxTime = thread['markers']['schema']['time']
|
||||
for marker in thread['markers']['data']:
|
||||
marker[idxTime] += delta
|
||||
else:
|
||||
for sample in thread['samples']:
|
||||
if "time" in sample:
|
||||
sample['time'] += delta
|
||||
for marker in thread['markers']:
|
||||
marker['time'] += delta
|
||||
|
||||
result = dict()
|
||||
result['profileJSON'] = dict()
|
||||
|
@ -149,6 +149,40 @@ status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const {
|
||||
const size_t N = mLedsByScanCode.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (mLedsByScanCode.valueAt(i).ledCode == ledCode) {
|
||||
*outScanCode = mLedsByScanCode.keyAt(i);
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode);
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode);
|
||||
#endif
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const {
|
||||
const size_t N = mLedsByUsageCode.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) {
|
||||
*outUsageCode = mLedsByUsageCode.keyAt(i);
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode);
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode);
|
||||
#endif
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
// --- KeyLayoutMap::Parser ---
|
||||
|
||||
@ -178,6 +212,10 @@ status_t KeyLayoutMap::Parser::parse() {
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
status_t status = parseAxis();
|
||||
if (status) return status;
|
||||
} else if (keywordToken == "led") {
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
status_t status = parseLed();
|
||||
if (status) return status;
|
||||
} else {
|
||||
ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
|
||||
keywordToken.string());
|
||||
@ -363,4 +401,46 @@ status_t KeyLayoutMap::Parser::parseAxis() {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::Parser::parseLed() {
|
||||
String8 codeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
bool mapUsage = false;
|
||||
if (codeToken == "usage") {
|
||||
mapUsage = true;
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
codeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
}
|
||||
char* end;
|
||||
int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
|
||||
if (*end) {
|
||||
ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
|
||||
mapUsage ? "usage" : "scan code", codeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
|
||||
if (map.indexOfKey(code) >= 0) {
|
||||
ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
|
||||
mapUsage ? "usage" : "scan code", codeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
int32_t ledCode = getLedByLabel(ledCodeToken.string());
|
||||
if (ledCode < 0) {
|
||||
ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
|
||||
ledCodeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
#if DEBUG_PARSER
|
||||
ALOGD("Parsed led %s: code=%d, ledCode=%d.",
|
||||
mapUsage ? "usage" : "scan code", code, ledCode);
|
||||
#endif
|
||||
|
||||
Led led;
|
||||
led.ledCode = ledCode;
|
||||
map.add(code, led);
|
||||
return NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
@ -67,6 +67,8 @@ public:
|
||||
status_t mapKey(int32_t scanCode, int32_t usageCode,
|
||||
int32_t* outKeyCode, uint32_t* outFlags) const;
|
||||
status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
|
||||
status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const;
|
||||
status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const;
|
||||
|
||||
status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;
|
||||
|
||||
@ -79,9 +81,16 @@ private:
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct Led {
|
||||
int32_t ledCode;
|
||||
};
|
||||
|
||||
|
||||
KeyedVector<int32_t, Key> mKeysByScanCode;
|
||||
KeyedVector<int32_t, Key> mKeysByUsageCode;
|
||||
KeyedVector<int32_t, AxisInfo> mAxes;
|
||||
KeyedVector<int32_t, Led> mLedsByScanCode;
|
||||
KeyedVector<int32_t, Led> mLedsByUsageCode;
|
||||
|
||||
KeyLayoutMap();
|
||||
|
||||
@ -99,6 +108,7 @@ private:
|
||||
private:
|
||||
status_t parseKey();
|
||||
status_t parseAxis();
|
||||
status_t parseLed();
|
||||
};
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user