Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-09-09 14:10:46 +02:00
commit 039287e013
136 changed files with 1194 additions and 1172 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 1193379 - Moving location of files under dom/bluetooth requires a clobber Bug 1201224 - stop unifying test package during mac universal builds needed a CLOBBER

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223"> <project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223"> <project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>

View File

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/> <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223"> <project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf"> <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223"> <project name="platform_build" path="build" remote="b2g" revision="e935894ef5f27e2f04b9e929a45a958e6288a223">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1,9 +1,9 @@
{ {
"git": { "git": {
"git_revision": "e69f2c86b931b723dd405115e33a1d02e6c5f5e6", "git_revision": "60e212543329ee48f2921e0cd92aaca4b4ce2f6a",
"remote": "https://git.mozilla.org/releases/gaia.git", "remote": "https://git.mozilla.org/releases/gaia.git",
"branch": "" "branch": ""
}, },
"revision": "410ec98908ee38c636b018d3ba92e17fb338db79", "revision": "8aa25dda878ebc1b075933633b69967b930b0726",
"repo_path": "integration/gaia-central" "repo_path": "integration/gaia-central"
} }

View File

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/> <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf"> <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -23,7 +23,7 @@
macanimationtype="document" macanimationtype="document"
fullscreenbutton="true" fullscreenbutton="true"
screenX="4" screenY="4" screenX="4" screenY="4"
width="640" height="480" width="800" height="600"
persist="screenX screenY width height sizemode"> persist="screenX screenY width height sizemode">
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script> <script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>

View File

@ -142,6 +142,7 @@ ProjectList.prototype = {
icon.setAttribute("src", opts.icon); icon.setAttribute("src", opts.icon);
opts.panel.appendChild(icon); opts.panel.appendChild(icon);
opts.panel.appendChild(span); opts.panel.appendChild(span);
opts.panel.setAttribute("title", opts.name);
} else { } else {
opts.panel.setAttribute("label", opts.name); opts.panel.setAttribute("label", opts.name);
opts.panel.setAttribute("image", opts.icon); opts.panel.setAttribute("image", opts.icon);

View File

@ -23,7 +23,7 @@ html, body {
} }
#custom-value-name { #custom-value-name {
width: 70%; width: 50%;
} }
header { header {
@ -38,13 +38,15 @@ header {
} }
#device-fields td { #device-fields td {
background-color: #f1f1f1; background-color: #F9F9F9;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #CCC;
border-right: 1px solid #fff; border-right: 1px solid #FFF;
font-size: 0.75em;
} }
#device-fields td:first-child { #device-fields td:first-child {
min-width: 400px; max-width: 250px;
min-width: 150px;
} }
#device-fields td.preference-name, #device-fields td.setting-name { #device-fields td.preference-name, #device-fields td.setting-name {
@ -65,7 +67,7 @@ header {
} }
#device-fields .custom-input { #device-fields .custom-input {
width: 300px; width: 130px;
} }
#search { #search {

View File

@ -4,7 +4,7 @@
html { html {
font: message-box; font: message-box;
font-size: 15px; font-size: 0.9em;
font-weight: normal; font-weight: normal;
margin: 0; margin: 0;
height: 100%; height: 100%;
@ -28,7 +28,7 @@ body {
} }
h1 { h1 {
font-size: 2.5em; font-size: 2em;
font-weight: lighter; font-weight: lighter;
line-height: 1.2; line-height: 1.2;
margin: 0; margin: 0;
@ -60,7 +60,7 @@ th, td {
} }
th { th {
min-width: 130px; min-width: 100px;
} }
th:first-of-type, td:first-of-type { th:first-of-type, td:first-of-type {

View File

@ -4,7 +4,7 @@
html { html {
font: message-box; font: message-box;
font-size: 12px; font-size: 11px;
font-weight: 400; font-weight: 400;
} }
@ -53,42 +53,59 @@ label,
position: relative; position: relative;
} }
.panel-item span {
display: block;
float: left;
overflow: hidden;
text-overflow: ellipsis;
width: 75%;
white-space: nowrap;
}
.panel-item { .panel-item {
padding: 3%; padding: 3%;
display: block; display: block;
background-color: #fff;
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
border-top: 1px solid #ededed;
border-left: 0;
width: 94%; width: 94%;
cursor: pointer;
border-top: 1px solid transparent;
border-left: 0;
border-bottom: 1px solid #CCC;
border-right: 0;
background-color: transparent;
} }
button.panel-item { button.panel-item {
background-position: 8px 8px; background-position: 5px 5px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 14px 14px; background-size: 14px 14px;
padding-left: 25px; padding-left: 25px;
width: 100%; width: 100%;
} }
button.project-panel-item-refreshtabs {
display: inline-block;
float: right;
padding: 3px;
text-transform: none;
width: auto;
margin: 0 4px 5px 5px;
}
.panel-item:disabled { .panel-item:disabled {
background-color: #FFF; background-color: #FFF;
color: #5A5A5A; color: #5A5A5A;
opacity: 0.5; opacity: 0.5;
cursor: default;
} }
.panel-item:not(:disabled):hover { #refresh-tabs {
background-color: #FFF;
border-top: 1px solid #EDEDED;
display: inline-block;
float: right;
padding: 3px;
text-transform: none;
border-right: 1px solid #CCC;
width: auto;
margin: 0 4px 5px 5px;
}
.panel-item:not(:disabled):hover,
button.panel-item:not(:disabled):hover,
#refresh-tabs:hover {
background-color: #CCF0FD; background-color: #CCF0FD;
border-top: 1px solid #EDEDED;
} }
.configure-button { .configure-button {
@ -101,7 +118,7 @@ button.project-panel-item-refreshtabs {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 14px 14px; background-size: 14px 14px;
position: absolute; position: absolute;
top: 0; top: -2px;
right: 0; right: 0;
border: 0; border: 0;
} }

View File

@ -162,10 +162,14 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
.panel-list { .panel-list {
display: none; display: none;
position: relative; position: relative;
max-width: 250px; max-width: 180px;
overflow: hidden; overflow: hidden;
} }
#project-listing-panel.panel-list {
max-width: 165px;
}
.panel-list-wrapper { .panel-list-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;

View File

@ -1,81 +0,0 @@
#!/usr/bin/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/.
import sys
import os
import hashlib
import json
import re
import errno
from argparse import ArgumentParser
def getFileHashAndSize(filename):
sha512Hash = 'UNKNOWN'
size = 'UNKNOWN'
try:
# open in binary mode to make sure we get consistent results
# across all platforms
f = open(filename, "rb")
shaObj = hashlib.sha512(f.read())
sha512Hash = shaObj.hexdigest()
size = os.path.getsize(filename)
except:
pass
return (sha512Hash, size)
def getMarProperties(filename, partial=False):
if not os.path.exists(filename):
return {}
(mar_hash, mar_size) = getFileHashAndSize(filename)
martype = 'partial' if partial else 'complete'
return {
'%sMarFilename' % martype: os.path.basename(filename),
'%sMarSize' % martype: mar_size,
'%sMarHash' % martype: mar_hash,
}
def getPartialInfo(props):
return [{
"from_buildid": props.get("previous_buildid"),
"size": props.get("partialMarSize"),
"hash": props.get("partialMarHash"),
"url": props.get("partialMarUrl"),
}]
if __name__ == '__main__':
parser = ArgumentParser(description='Generate mach_build_properties.json for automation builds.')
parser.add_argument("--complete-mar-file", required=True,
action="store", dest="complete_mar_file",
help="Path to the complete MAR file, relative to the objdir.")
parser.add_argument("--partial-mar-file", required=False,
action="store", dest="partial_mar_file",
help="Path to the partial MAR file, relative to the objdir.")
parser.add_argument("--upload-properties", required=False,
action="store", dest="upload_properties",
help="Path to the properties written by 'make upload'")
args = parser.parse_args()
json_data = getMarProperties(args.complete_mar_file)
if args.upload_properties:
with open(args.upload_properties) as f:
json_data.update(json.load(f))
if args.partial_mar_file:
json_data.update(getMarProperties(args.partial_mar_file, partial=True))
# Pull the previous buildid from the partial mar filename.
res = re.match(r'.*\.([0-9]+)-[0-9]+.mar', args.partial_mar_file)
if res:
json_data['previous_buildid'] = res.group(1)
# Set partialInfo to be a collection of the partial mar properties
# useful for balrog.
json_data['partialInfo'] = getPartialInfo(json_data)
with open('mach_build_properties.json', 'w') as outfile:
json.dump(json_data, outfile, indent=4)

View File

@ -17,11 +17,6 @@ include $(topsrcdir)/toolkit/mozapps/installer/upload-files.mk
# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds) # Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
DIST_FILES = DIST_FILES =
ifeq (1,$(MOZ_AUTOMATION_UPLOAD))
# Properties from 'make upload' that are file URLs.
AUTOMATION_UPLOAD_PROPERTIES = --upload-properties $(DIST)/upload-properties.json
endif
# Helper variables to convert from MOZ_AUTOMATION_* variables to the # Helper variables to convert from MOZ_AUTOMATION_* variables to the
# corresponding the make target # corresponding the make target
tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols
@ -100,7 +95,7 @@ automation/l10n-check: automation/pretty-l10n-check
automation/update-packaging: automation/pretty-update-packaging automation/update-packaging: automation/pretty-update-packaging
automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS)) automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
$(PYTHON) $(topsrcdir)/build/gen_mach_buildprops.py --complete-mar-file $(DIST)/$(COMPLETE_MAR) $(addprefix --partial-mar-file ,$(wildcard $(DIST)/$(PARTIAL_MAR))) $(AUTOMATION_UPLOAD_PROPERTIES) @echo Automation steps completed.
# Note: We have to force -j1 here, at least until bug 1036563 is fixed. # Note: We have to force -j1 here, at least until bug 1036563 is fixed.
AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1 AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1

View File

@ -8,7 +8,12 @@
# to be set: # to be set:
# UPLOAD_HOST : host to upload files to # UPLOAD_HOST : host to upload files to
# UPLOAD_USER : username on that host # UPLOAD_USER : username on that host
# and one of the following:
# UPLOAD_PATH : path on that host to put the files in # UPLOAD_PATH : path on that host to put the files in
# UPLOAD_TO_TEMP : upload files to a new temporary directory
#
# If UPLOAD_HOST and UPLOAD_USER are not set, this script will simply write out
# the properties file.
# #
# And will use the following optional environment variables if set: # And will use the following optional environment variables if set:
# UPLOAD_SSH_KEY : path to a ssh private key to use # UPLOAD_SSH_KEY : path to a ssh private key to use
@ -25,18 +30,12 @@
import sys, os import sys, os
import re import re
import json import json
import errno
import hashlib
from optparse import OptionParser from optparse import OptionParser
from subprocess import check_call, check_output, STDOUT from subprocess import check_call, check_output, STDOUT
import redo import redo
def RequireEnvironmentVariable(v):
"""Return the value of the environment variable named v, or print
an error and exit if it's unset (or empty)."""
if not v in os.environ or os.environ[v] == "":
print "Error: required environment variable %s not set" % v
sys.exit(1)
return os.environ[v]
def OptionalEnvironmentVariable(v): def OptionalEnvironmentVariable(v):
"""Return the value of the environment variable named v, or None """Return the value of the environment variable named v, or None
if it's unset (or empty).""" if it's unset (or empty)."""
@ -119,6 +118,33 @@ def GetRemotePath(path, local_file, base_path):
dir = dir[len(base_path)+1:].replace('\\','/') dir = dir[len(base_path)+1:].replace('\\','/')
return path + dir return path + dir
def GetFileHashAndSize(filename):
sha512Hash = 'UNKNOWN'
size = 'UNKNOWN'
try:
# open in binary mode to make sure we get consistent results
# across all platforms
with open(filename, "rb") as f:
shaObj = hashlib.sha512(f.read())
sha512Hash = shaObj.hexdigest()
size = os.path.getsize(filename)
except:
raise Exception("Unable to get filesize/hash from file: %s" % filename)
return (sha512Hash, size)
def GetMarProperties(filename):
if not os.path.exists(filename):
return {}
(mar_hash, mar_size) = GetFileHashAndSize(filename)
return {
'completeMarFilename': os.path.basename(filename),
'completeMarSize': mar_size,
'completeMarHash': mar_hash,
}
def GetUrlProperties(output, package): def GetUrlProperties(output, package):
# let's create a switch case using name-spaces/dict # let's create a switch case using name-spaces/dict
# rather than a long if/else with duplicate code # rather than a long if/else with duplicate code
@ -156,7 +182,7 @@ def GetUrlProperties(output, package):
properties = {prop: 'UNKNOWN' for prop, condition in property_conditions} properties = {prop: 'UNKNOWN' for prop, condition in property_conditions}
return properties return properties
def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None, base_path=None, upload_to_temp_dir=False, post_upload_command=None, properties_file=None, package=None): def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None, base_path=None, upload_to_temp_dir=False, post_upload_command=None, package=None):
"""Upload each file in the list files to user@host:path. Optionally pass """Upload each file in the list files to user@host:path. Optionally pass
port and ssh_key to the ssh commands. If base_path is not None, upload port and ssh_key to the ssh commands. If base_path is not None, upload
files including their path relative to base_path. If upload_to_temp_dir is files including their path relative to base_path. If upload_to_temp_dir is
@ -167,6 +193,13 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
after uploading all files, passing it the upload path, and the full paths to after uploading all files, passing it the upload path, and the full paths to
all files uploaded. all files uploaded.
If verbose is True, print status updates while working.""" If verbose is True, print status updates while working."""
if not host or not user:
return {}
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
"defined."
sys.exit(1)
if upload_to_temp_dir: if upload_to_temp_dir:
path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key) path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
if not path.endswith("/"): if not path.endswith("/"):
@ -174,6 +207,7 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
if base_path is not None: if base_path is not None:
base_path = os.path.abspath(base_path) base_path = os.path.abspath(base_path)
remote_files = [] remote_files = []
properties = {}
try: try:
for file in files: for file in files:
file = os.path.abspath(file) file = os.path.abspath(file)
@ -193,22 +227,28 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
output = DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key) output = DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
# We print since mozharness may parse URLs from the output stream. # We print since mozharness may parse URLs from the output stream.
print output print output
if properties_file: properties = GetUrlProperties(output, package)
with open(properties_file, 'w') as outfile:
properties = GetUrlProperties(output, package)
properties['packageFilename'] = package
properties['uploadFiles'] = [os.path.abspath(f) for f in files]
json.dump(properties, outfile, indent=4)
finally: finally:
if upload_to_temp_dir: if upload_to_temp_dir:
DoSSHCommand("rm -rf %s" % path, user, host, port=port, DoSSHCommand("rm -rf %s" % path, user, host, port=port,
ssh_key=ssh_key) ssh_key=ssh_key)
if verbose: if verbose:
print "Upload complete" print "Upload complete"
return properties
def WriteProperties(files, properties_file, url_properties, package):
properties = url_properties
for file in files:
if file.endswith('.complete.mar'):
properties.update(GetMarProperties(file))
with open(properties_file, 'w') as outfile:
properties['packageFilename'] = package
properties['uploadFiles'] = [os.path.abspath(f) for f in files]
json.dump(properties, outfile, indent=4)
if __name__ == '__main__': if __name__ == '__main__':
host = RequireEnvironmentVariable('UPLOAD_HOST') host = OptionalEnvironmentVariable('UPLOAD_HOST')
user = RequireEnvironmentVariable('UPLOAD_USER') user = OptionalEnvironmentVariable('UPLOAD_USER')
path = OptionalEnvironmentVariable('UPLOAD_PATH') path = OptionalEnvironmentVariable('UPLOAD_PATH')
upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP') upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
port = OptionalEnvironmentVariable('UPLOAD_PORT') port = OptionalEnvironmentVariable('UPLOAD_PORT')
@ -216,10 +256,7 @@ if __name__ == '__main__':
port = int(port) port = int(port)
key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY') key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD') post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD')
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
"defined."
sys.exit(1)
if sys.platform == 'win32': if sys.platform == 'win32':
if path is not None: if path is not None:
path = FixupMsysPath(path) path = FixupMsysPath(path)
@ -240,12 +277,16 @@ if __name__ == '__main__':
if len(args) < 1: if len(args) < 1:
print "You must specify at least one file to upload" print "You must specify at least one file to upload"
sys.exit(1) sys.exit(1)
if not options.properties_file:
print "You must specify a --properties-file"
sys.exit(1)
try: try:
UploadFiles(user, host, path, args, base_path=options.base_path, url_properties = UploadFiles(user, host, path, args, base_path=options.base_path,
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir, port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
post_upload_command=post_upload_command, post_upload_command=post_upload_command,
properties_file=options.properties_file, package=options.package, package=options.package,
verbose=True) verbose=True)
WriteProperties(args, options.properties_file, url_properties, options.package)
except IOError, (strerror): except IOError, (strerror):
print strerror print strerror
sys.exit(1) sys.exit(1)

View File

@ -1595,6 +1595,7 @@ if test "$GNU_CXX"; then
# -Woverloaded-virtual - function declaration hides virtual function from base class # -Woverloaded-virtual - function declaration hides virtual function from base class
# -Wparentheses - catches `if (a=b)` and operator precedence bugs # -Wparentheses - catches `if (a=b)` and operator precedence bugs
# -Wpointer-arith - catches pointer arithmetic using NULL or sizeof(void) # -Wpointer-arith - catches pointer arithmetic using NULL or sizeof(void)
# -Wrange-loop-analysis - catches copies during range-based for loops.
# -Wreturn-type - catches missing returns, zero false positives # -Wreturn-type - catches missing returns, zero false positives
# -Wsequence-point - catches undefined order behavior like `a = a++` # -Wsequence-point - catches undefined order behavior like `a = a++`
# -Wsign-compare - catches comparison of signed and unsigned types # -Wsign-compare - catches comparison of signed and unsigned types
@ -1626,6 +1627,7 @@ if test "$GNU_CXX"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=unused-label" _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=unused-label"
MOZ_CXX_SUPPORTS_WARNING(-Werror=, non-literal-null-conversion, ac_cxx_has_werror_non_literal_null_conversion) MOZ_CXX_SUPPORTS_WARNING(-Werror=, non-literal-null-conversion, ac_cxx_has_werror_non_literal_null_conversion)
MOZ_CXX_SUPPORTS_WARNING(-Werror=, range-loop-analysis, ac_cxx_has_range_loop_analysis)
MOZ_CXX_SUPPORTS_WARNING(-Werror=, sometimes-uninitialized, ac_cxx_has_sometimes_uninitialized) MOZ_CXX_SUPPORTS_WARNING(-Werror=, sometimes-uninitialized, ac_cxx_has_sometimes_uninitialized)
fi fi

View File

@ -190,6 +190,30 @@ FlattenedChildIterator::Init(bool aIgnoreXBL)
} }
} }
void
ExplicitChildIterator::Seek(nsIContent* aChildToFind)
{
if (aChildToFind->GetParent() == mParent &&
!aChildToFind->IsRootOfAnonymousSubtree()) {
// Fast path: just point ourselves to aChildToFind, which is a
// normal DOM child of ours.
MOZ_ASSERT(!ShadowRoot::IsShadowInsertionPoint(aChildToFind));
MOZ_ASSERT(!nsContentUtils::IsContentInsertionPoint(aChildToFind));
mChild = aChildToFind;
mIndexInInserted = 0;
mShadowIterator = nullptr;
mDefaultChild = nullptr;
mIsFirst = false;
return;
}
// Can we add more fast paths here based on whether the parent of aChildToFind
// is a shadow insertion point or content insertion point?
// Slow path: just walk all our kids.
Seek(aChildToFind, nullptr);
}
nsIContent* nsIContent*
ExplicitChildIterator::Get() ExplicitChildIterator::Get()
{ {

View File

@ -60,16 +60,24 @@ public:
nsIContent* GetNextChild(); nsIContent* GetNextChild();
// Looks for aChildToFind respecting insertion points until aChildToFind // Looks for aChildToFind respecting insertion points until aChildToFind is
// found. This version can take shortcuts that the two-argument version
// can't, so can be faster (and in fact can be O(1) instead of O(N) in many
// cases).
void Seek(nsIContent* aChildToFind);
// Looks for aChildToFind respecting insertion points until aChildToFind is found.
// or aBound is found. If aBound is nullptr then the seek is unbounded. Returns // or aBound is found. If aBound is nullptr then the seek is unbounded. Returns
// whether aChildToFind was found as an explicit child prior to encountering // whether aChildToFind was found as an explicit child prior to encountering
// aBound. // aBound.
bool Seek(nsIContent* aChildToFind, nsIContent* aBound = nullptr) bool Seek(nsIContent* aChildToFind, nsIContent* aBound)
{ {
// It would be nice to assert that we find aChildToFind, but bz thinks that // It would be nice to assert that we find aChildToFind, but bz thinks that
// we might not find aChildToFind when called from ContentInserted // we might not find aChildToFind when called from ContentInserted
// if first-letter frames are about. // if first-letter frames are about.
// We can't easily take shortcuts here because we'd have to have a way to
// compare aChildToFind to aBound.
nsIContent* child; nsIContent* child;
do { do {
child = GetNextChild(); child = GetNextChild();

View File

@ -316,7 +316,7 @@ ShadowRoot::DistributeSingleNode(nsIContent* aContent)
if (!isIndexFound) { if (!isIndexFound) {
// We have still not found an index in the insertion point, // We have still not found an index in the insertion point,
// thus it must be at the end. // thus it must be at the end.
MOZ_ASSERT(childIterator.Seek(aContent), MOZ_ASSERT(childIterator.Seek(aContent, nullptr),
"Trying to match a node that is not a candidate to be matched"); "Trying to match a node that is not a candidate to be matched");
insertionPoint->AppendMatchedNode(aContent); insertionPoint->AppendMatchedNode(aContent);
} }

View File

@ -42,3 +42,7 @@ method SVGSVGElement.getElementById
attribute SVGSVGElement.currentScale attribute SVGSVGElement.currentScale
property Fill property Fill
property FillOpacity property FillOpacity
// Push API
method PushManager.subscribe
method PushSubscription.unsubscribe

View File

@ -631,8 +631,8 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
*aActionTaken = false; *aActionTaken = false;
} }
NS_ASSERTION(aEventMessage == NS_CUT || aEventMessage == NS_COPY || NS_ASSERTION(aEventMessage == eCut || aEventMessage == eCopy ||
aEventMessage == NS_PASTE, aEventMessage == ePaste,
"Invalid clipboard event type"); "Invalid clipboard event type");
nsCOMPtr<nsIPresShell> presShell = aPresShell; nsCOMPtr<nsIPresShell> presShell = aPresShell;
@ -688,7 +688,7 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
nsRefPtr<DataTransfer> clipboardData; nsRefPtr<DataTransfer> clipboardData;
if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) { if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
clipboardData = clipboardData =
new DataTransfer(piWindow, aEventMessage, aEventMessage == NS_PASTE, new DataTransfer(piWindow, aEventMessage, aEventMessage == ePaste,
aClipboardType); aClipboardType);
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
@ -703,7 +703,7 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
// No need to do anything special during a paste. Either an event listener // No need to do anything special during a paste. Either an event listener
// took care of it and cancelled the event, or the caller will handle it. // took care of it and cancelled the event, or the caller will handle it.
// Return true to indicate that the event wasn't cancelled. // Return true to indicate that the event wasn't cancelled.
if (aEventMessage == NS_PASTE) { if (aEventMessage == ePaste) {
// Clear and mark the clipboardData as readonly. This prevents someone // Clear and mark the clipboardData as readonly. This prevents someone
// from reading the clipboard contents after the paste event has fired. // from reading the clipboard contents after the paste event has fired.
if (clipboardData) { if (clipboardData) {
@ -743,7 +743,7 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
// when cutting non-editable content, do nothing // when cutting non-editable content, do nothing
// XXX this is probably the wrong editable flag to check // XXX this is probably the wrong editable flag to check
if (aEventMessage != NS_CUT || content->IsEditable()) { if (aEventMessage != eCut || content->IsEditable()) {
// get the data from the selection if any // get the data from the selection if any
bool isCollapsed; bool isCollapsed;
sel->GetIsCollapsed(&isCollapsed); sel->GetIsCollapsed(&isCollapsed);

View File

@ -64,8 +64,8 @@ class nsCopySupport
/** /**
* Fires a cut, copy or paste event, on the given presshell, depending * Fires a cut, copy or paste event, on the given presshell, depending
* on the value of aEventMessage, which should be either NS_CUT, NS_COPY or * on the value of aEventMessage, which should be either eCut, eCopy or
* NS_PASTE, and perform the default copy action if the event was not * ePaste, and perform the default copy action if the event was not
* cancelled. * cancelled.
* *
* If aSelection is specified, then this selection is used as the target * If aSelection is specified, then this selection is used as the target

View File

@ -2026,7 +2026,7 @@ nsDOMWindowUtils::SendSelectionSetEvent(uint32_t aOffset,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
WidgetSelectionEvent selectionEvent(true, NS_SELECTION_SET, widget); WidgetSelectionEvent selectionEvent(true, eSetSelection, widget);
InitEvent(selectionEvent); InitEvent(selectionEvent);
selectionEvent.mOffset = aOffset; selectionEvent.mOffset = aOffset;

View File

@ -8593,9 +8593,6 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
// The misspelled key 'referer' is as per the HTTP spec // The misspelled key 'referer' is as per the HTTP spec
rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("referer"), rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("referer"),
mReferrer); mReferrer);
if (NS_FAILED(rv)) {
mReferrer.Truncate();
}
static const char *const headers[] = { static const char *const headers[] = {
"default-style", "default-style",

View File

@ -6918,7 +6918,9 @@ nsGlobalWindow::AlertOrConfirm(bool aAlert,
MOZ_ASSERT(IsOuterWindow()); MOZ_ASSERT(IsOuterWindow());
if (!AreDialogsEnabled()) { if (!AreDialogsEnabled()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE); // Just silently return. In the case of alert(), the return value is
// ignored. In the case of confirm(), returning false is the same thing as
// would happen if the user cancels.
return false; return false;
} }
@ -7058,7 +7060,7 @@ nsGlobalWindow::PromptOuter(const nsAString& aMessage, const nsAString& aInitial
SetDOMStringToNull(aReturn); SetDOMStringToNull(aReturn);
if (!AreDialogsEnabled()) { if (!AreDialogsEnabled()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE); // Return null, as if the user just canceled the prompt.
return; return;
} }
@ -7496,6 +7498,8 @@ nsGlobalWindow::PrintOuter(ErrorResult& aError)
} }
if (!AreDialogsEnabled()) { if (!AreDialogsEnabled()) {
// We probably want to keep throwing here; silently doing nothing is a bit
// weird given the typical use cases of print().
aError.Throw(NS_ERROR_NOT_AVAILABLE); aError.Throw(NS_ERROR_NOT_AVAILABLE);
return; return;
} }
@ -9553,6 +9557,8 @@ nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgumen
EnsureReflowFlushAndPaint(); EnsureReflowFlushAndPaint();
if (!AreDialogsEnabled()) { if (!AreDialogsEnabled()) {
// We probably want to keep throwing here; silently doing nothing is a bit
// weird given the typical use cases of showModalDialog().
aError.Throw(NS_ERROR_NOT_AVAILABLE); aError.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr; return nullptr;
} }

View File

@ -520,9 +520,9 @@ nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell(); nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
EventMessage eventMessage = NS_COPY; EventMessage eventMessage = eCopy;
if (strcmp(aCommandName, "cmd_cut") == 0) { if (strcmp(aCommandName, "cmd_cut") == 0) {
eventMessage = NS_CUT; eventMessage = eCut;
} }
bool actionTaken = false; bool actionTaken = false;

View File

@ -12,6 +12,7 @@
#include "BluetoothUuid.h" #include "BluetoothUuid.h"
#include "ObexBase.h" #include "ObexBase.h"
#include "mozilla/dom/BluetoothPbapParametersBinding.h"
#include "mozilla/dom/File.h" #include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@ -527,29 +528,26 @@ BluetoothPbapManager::AppendBtNamedValueByTagId(
const AppParameterTag aTagId) const AppParameterTag aTagId)
{ {
uint8_t buf[64]; uint8_t buf[64];
if (!aHeader.GetAppParameter(aTagId, buf, 64)) {
return;
}
switch (aTagId) { switch (aTagId) {
case AppParameterTag::Order: { case AppParameterTag::Order: {
if (!aHeader.GetAppParameter(AppParameterTag::Order, buf, 64)) { using namespace mozilla::dom::vCardOrderTypeValues;
break; uint32_t order = buf[0] < ArrayLength(strings) ? (uint32_t) buf[0]
} : 0; // default: indexed
BT_APPEND_NAMED_VALUE(aValues, "order", order);
static const nsString sOrderStr[] = {NS_LITERAL_STRING("alphanumeric"), break;
NS_LITERAL_STRING("indexed"), }
NS_LITERAL_STRING("phonetical")}; case AppParameterTag::SearchProperty: {
uint8_t order = buf[0]; using namespace mozilla::dom::vCardSearchKeyTypeValues;
if (order < MOZ_ARRAY_LENGTH(sOrderStr)) { uint32_t searchKey = buf[0] < ArrayLength(strings) ? (uint32_t) buf[0]
BT_APPEND_NAMED_VALUE(aValues, "order", sOrderStr[order]); : 0; // default: name
} else { BT_APPEND_NAMED_VALUE(aValues, "searchKey", searchKey);
BT_LOGR("Unexpected value %d of 'Order'", order);
}
break; break;
} }
case AppParameterTag::SearchValue: { case AppParameterTag::SearchValue: {
if (!aHeader.GetAppParameter(AppParameterTag::SearchValue, buf, 64)) {
break;
}
// Section 5.3.4.3 "SearchValue {<text string>}", PBAP 1.2 // Section 5.3.4.3 "SearchValue {<text string>}", PBAP 1.2
// The UTF-8 character set shall be used for <text string>. // The UTF-8 character set shall be used for <text string>.
@ -560,27 +558,7 @@ BluetoothPbapManager::AppendBtNamedValueByTagId(
BT_APPEND_NAMED_VALUE(aValues, "searchText", text); BT_APPEND_NAMED_VALUE(aValues, "searchText", text);
break; break;
} }
case AppParameterTag::SearchProperty: {
if (!aHeader.GetAppParameter(AppParameterTag::SearchProperty, buf, 64)) {
break;
}
static const nsString sSearchKeyStr[] = {NS_LITERAL_STRING("name"),
NS_LITERAL_STRING("number"),
NS_LITERAL_STRING("sound")};
uint8_t searchKey = buf[0];
if (searchKey < MOZ_ARRAY_LENGTH(sSearchKeyStr)) {
BT_APPEND_NAMED_VALUE(aValues, "searchKey", sSearchKeyStr[searchKey]);
} else {
BT_LOGR("Unexpected value %d of 'SearchProperty'", searchKey);
}
break;
}
case AppParameterTag::MaxListCount: { case AppParameterTag::MaxListCount: {
if (!aHeader.GetAppParameter(AppParameterTag::MaxListCount, buf, 64)) {
break;
}
uint16_t maxListCount = *((uint16_t *)buf); uint16_t maxListCount = *((uint16_t *)buf);
// convert big endian to little endian // convert big endian to little endian
@ -595,10 +573,6 @@ BluetoothPbapManager::AppendBtNamedValueByTagId(
break; break;
} }
case AppParameterTag::ListStartOffset: { case AppParameterTag::ListStartOffset: {
if (!aHeader.GetAppParameter(AppParameterTag::ListStartOffset, buf, 64)) {
break;
}
uint16_t listStartOffset = *((uint16_t *)buf); uint16_t listStartOffset = *((uint16_t *)buf);
// convert big endian to little endian // convert big endian to little endian
@ -609,30 +583,17 @@ BluetoothPbapManager::AppendBtNamedValueByTagId(
break; break;
} }
case AppParameterTag::PropertySelector: { case AppParameterTag::PropertySelector: {
if (!aHeader.GetAppParameter(
AppParameterTag::PropertySelector, buf, 64)) {
break;
}
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64); InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
BT_APPEND_NAMED_VALUE(aValues, "propSelector", props); BT_APPEND_NAMED_VALUE(aValues, "propSelector", props);
break; break;
} }
case AppParameterTag::Format: { case AppParameterTag::Format: {
if (!aHeader.GetAppParameter(AppParameterTag::Format, buf, 64)) {
break;
}
bool usevCard3 = buf[0]; bool usevCard3 = buf[0];
BT_APPEND_NAMED_VALUE(aValues, "format", usevCard3); BT_APPEND_NAMED_VALUE(aValues, "format", usevCard3);
break; break;
} }
case AppParameterTag::vCardSelector: { case AppParameterTag::vCardSelector: {
if (!aHeader.GetAppParameter(AppParameterTag::vCardSelector, buf, 64)) {
break;
}
InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64); InfallibleTArray<uint32_t> props = PackPropertiesMask(buf, 64);
bool hasVCardSelectorOperator = aHeader.GetAppParameter( bool hasVCardSelectorOperator = aHeader.GetAppParameter(

View File

@ -1295,11 +1295,11 @@ BluetoothAdapter::HandlePullVCardListingReq(const BluetoothValue& aValue)
if (name.EqualsLiteral("name")) { if (name.EqualsLiteral("name")) {
init.mName = value.get_nsString(); init.mName = value.get_nsString();
} else if (name.EqualsLiteral("order")) { } else if (name.EqualsLiteral("order")) {
init.mOrder = ConvertStringToVCardOrderType(value.get_nsString()); init.mOrder = static_cast<vCardOrderType>(value.get_uint32_t());
} else if (name.EqualsLiteral("searchKey")) {
init.mSearchKey = static_cast<vCardSearchKeyType>(value.get_uint32_t());
} else if (name.EqualsLiteral("searchText")) { } else if (name.EqualsLiteral("searchText")) {
init.mSearchValue = value.get_nsString(); init.mSearchValue = value.get_nsString();
} else if (name.EqualsLiteral("searchKey")) {
init.mSearchKey = ConvertStringToVCardSearchKeyType(value.get_nsString());
} else if (name.EqualsLiteral("maxListCount")) { } else if (name.EqualsLiteral("maxListCount")) {
init.mMaxListCount = value.get_uint32_t(); init.mMaxListCount = value.get_uint32_t();
} else if (name.EqualsLiteral("listStartOffset")) { } else if (name.EqualsLiteral("listStartOffset")) {
@ -1338,40 +1338,6 @@ BluetoothAdapter::getVCardProperties(const BluetoothValue &aValue)
return propSelector; return propSelector;
} }
vCardOrderType
BluetoothAdapter::ConvertStringToVCardOrderType(const nsAString& aString)
{
using namespace mozilla::dom::vCardOrderTypeValues;
for (size_t index = 0; index < ArrayLength(strings) - 1; index++) {
if (aString.LowerCaseEqualsASCII(strings[index].value,
strings[index].length)) {
return static_cast<vCardOrderType>(index);
}
}
BT_WARNING("Treat the unexpected string '%s' as vCardOrderType::Indexed",
NS_ConvertUTF16toUTF8(aString).get());
return vCardOrderType::Indexed; // The default value is 'Indexed'.
}
vCardSearchKeyType
BluetoothAdapter::ConvertStringToVCardSearchKeyType(const nsAString& aString)
{
using namespace mozilla::dom::vCardSearchKeyTypeValues;
for (size_t index = 0; index < ArrayLength(strings) - 1; index++) {
if (aString.LowerCaseEqualsASCII(strings[index].value,
strings[index].length)) {
return static_cast<vCardSearchKeyType>(index);
}
}
BT_WARNING("Treat the unexpected string '%s' as vCardSearchKeyType::Name",
NS_ConvertUTF16toUTF8(aString).get());
return vCardSearchKeyType::Name; // The default value is 'Name'.
}
void void
BluetoothAdapter::DispatchAttributeEvent(const Sequence<nsString>& aTypes) BluetoothAdapter::DispatchAttributeEvent(const Sequence<nsString>& aTypes)
{ {

View File

@ -342,21 +342,6 @@ private:
*/ */
Sequence<vCardProperties> getVCardProperties(const BluetoothValue &aValue); Sequence<vCardProperties> getVCardProperties(const BluetoothValue &aValue);
/**
* Convert string to vCardOrderType.
*
* @param aString [in] String to convert
*/
vCardOrderType ConvertStringToVCardOrderType(const nsAString& aString);
/**
* Convert string to vCardSearchKeyType.
*
* @param aString [in] String to convert
*/
vCardSearchKeyType ConvertStringToVCardSearchKeyType(
const nsAString& aString);
/** /**
* Fire BluetoothAttributeEvent to trigger onattributechanged event handler. * Fire BluetoothAttributeEvent to trigger onattributechanged event handler.
* *

View File

@ -79,7 +79,7 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
// Always create a clipboardData for the copy event. If this is changed to // Always create a clipboardData for the copy event. If this is changed to
// support other types of events, make sure that read/write privileges are // support other types of events, make sure that read/write privileges are
// checked properly within DataTransfer. // checked properly within DataTransfer.
clipboardData = new DataTransfer(ToSupports(e), NS_COPY, false, -1); clipboardData = new DataTransfer(ToSupports(e), eCopy, false, -1);
clipboardData->SetData(aParam.mDataType, aParam.mData); clipboardData->SetData(aParam.mDataType, aParam.mData);
} }
} }
@ -105,11 +105,11 @@ ClipboardEvent::GetClipboardData()
if (!event->clipboardData) { if (!event->clipboardData) {
if (mEventIsInternal) { if (mEventIsInternal) {
event->clipboardData = event->clipboardData =
new DataTransfer(ToSupports(this), NS_COPY, false, -1); new DataTransfer(ToSupports(this), eCopy, false, -1);
} else { } else {
event->clipboardData = event->clipboardData =
new DataTransfer(ToSupports(this), event->mMessage, new DataTransfer(ToSupports(this), event->mMessage,
event->mMessage == NS_PASTE, event->mMessage == ePaste,
nsIClipboard::kGlobalClipboard); nsIClipboard::kGlobalClipboard);
} }
} }

View File

@ -86,13 +86,13 @@ DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
// For these events, we want to be able to add data to the data transfer, so // For these events, we want to be able to add data to the data transfer, so
// clear the readonly state. Otherwise, the data is already present. For // clear the readonly state. Otherwise, the data is already present. For
// external usage, cache the data from the native clipboard or drag. // external usage, cache the data from the native clipboard or drag.
if (aEventMessage == NS_CUT || if (aEventMessage == eCut ||
aEventMessage == NS_COPY || aEventMessage == eCopy ||
aEventMessage == eDragStart || aEventMessage == eDragStart ||
aEventMessage == eLegacyDragGesture) { aEventMessage == eLegacyDragGesture) {
mReadOnly = false; mReadOnly = false;
} else if (mIsExternal) { } else if (mIsExternal) {
if (aEventMessage == NS_PASTE) { if (aEventMessage == ePaste) {
CacheExternalClipboardFormats(); CacheExternalClipboardFormats();
} else if (aEventMessage >= eDragDropEventFirst && } else if (aEventMessage >= eDragDropEventFirst &&
aEventMessage <= eDragDropEventLast) { aEventMessage <= eDragDropEventLast) {
@ -271,7 +271,7 @@ DataTransfer::GetFiles(ErrorResult& aRv)
{ {
if (mEventMessage != eDrop && if (mEventMessage != eDrop &&
mEventMessage != eLegacyDragDrop && mEventMessage != eLegacyDragDrop &&
mEventMessage != NS_PASTE) { mEventMessage != ePaste) {
return nullptr; return nullptr;
} }
@ -543,8 +543,8 @@ DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv)
{ {
// Only the first item is valid for clipboard events // Only the first item is valid for clipboard events
if (aIndex > 0 && if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY || (mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == NS_PASTE)) { mEventMessage == ePaste)) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr; return nullptr;
} }
@ -584,8 +584,8 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
// Only the first item is valid for clipboard events // Only the first item is valid for clipboard events
if (aIndex > 0 && if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY || (mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == NS_PASTE)) { mEventMessage == ePaste)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR; return NS_ERROR_DOM_INDEX_SIZE_ERR;
} }
@ -604,7 +604,7 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* principal = nullptr; nsIPrincipal* principal = nullptr;
if (mIsCrossDomainSubFrameDrop || if (mIsCrossDomainSubFrameDrop ||
(mEventMessage != eDrop && mEventMessage != eLegacyDragDrop && (mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
mEventMessage != NS_PASTE && mEventMessage != ePaste &&
!nsContentUtils::IsCallerChrome())) { !nsContentUtils::IsCallerChrome())) {
principal = nsContentUtils::SubjectPrincipal(); principal = nsContentUtils::SubjectPrincipal();
} }
@ -696,8 +696,8 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
// Only the first item is valid for clipboard events // Only the first item is valid for clipboard events
if (aIndex > 0 && if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY || (mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == NS_PASTE)) { mEventMessage == ePaste)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR; return NS_ERROR_DOM_INDEX_SIZE_ERR;
} }
@ -742,8 +742,8 @@ DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
// Only the first item is valid for clipboard events // Only the first item is valid for clipboard events
if (aIndex > 0 && if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY || (mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == NS_PASTE)) { mEventMessage == ePaste)) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return; return;
} }
@ -758,8 +758,8 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(!mReadOnly); MOZ_ASSERT(!mReadOnly);
MOZ_ASSERT(aIndex < mItems.Length()); MOZ_ASSERT(aIndex < mItems.Length());
MOZ_ASSERT(aIndex == 0 || MOZ_ASSERT(aIndex == 0 ||
(mEventMessage != NS_CUT && mEventMessage != NS_COPY && (mEventMessage != eCut && mEventMessage != eCopy &&
mEventMessage != NS_PASTE)); mEventMessage != ePaste));
nsAutoString format; nsAutoString format;
GetRealFormat(aFormat, format); GetRealFormat(aFormat, format);
@ -1258,7 +1258,7 @@ DataTransfer::CacheExternalDragFormats()
void void
DataTransfer::CacheExternalClipboardFormats() DataTransfer::CacheExternalClipboardFormats()
{ {
NS_ASSERTION(mEventMessage == NS_PASTE, NS_ASSERTION(mEventMessage == ePaste,
"caching clipboard data for invalid event"); "caching clipboard data for invalid event");
// Called during the constructor for paste events to cache the formats // Called during the constructor for paste events to cache the formats
@ -1300,7 +1300,7 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
} }
// only drag and paste events should be calling FillInExternalData // only drag and paste events should be calling FillInExternalData
NS_ASSERTION(mEventMessage != NS_CUT && mEventMessage != NS_COPY, NS_ASSERTION(mEventMessage != eCut && mEventMessage != eCopy,
"clipboard event with empty data"); "clipboard event with empty data");
NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat); NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
@ -1318,7 +1318,7 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
trans->Init(nullptr); trans->Init(nullptr);
trans->AddDataFlavor(format); trans->AddDataFlavor(format);
if (mEventMessage == NS_PASTE) { if (mEventMessage == ePaste) {
MOZ_ASSERT(aIndex == 0, "index in clipboard must be 0"); MOZ_ASSERT(aIndex == 0, "index in clipboard must be 0");
nsCOMPtr<nsIClipboard> clipboard = do_GetService("@mozilla.org/widget/clipboard;1"); nsCOMPtr<nsIClipboard> clipboard = do_GetService("@mozilla.org/widget/clipboard;1");

View File

@ -153,11 +153,11 @@ EVENT(abort,
EventNameType_All, EventNameType_All,
eBasicEventClass) eBasicEventClass)
EVENT(canplay, EVENT(canplay,
NS_CANPLAY, eCanPlay,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(canplaythrough, EVENT(canplaythrough,
NS_CANPLAYTHROUGH, eCanPlayThrough,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(change, EVENT(change,
@ -207,15 +207,15 @@ EVENT(drop,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eDragEventClass) eDragEventClass)
EVENT(durationchange, EVENT(durationchange,
NS_DURATIONCHANGE, eDurationChange,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(emptied, EVENT(emptied,
NS_EMPTIED, eEmptied,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(ended, EVENT(ended,
NS_ENDED, eEnded,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(input, EVENT(input,
@ -255,15 +255,15 @@ NON_IDL_EVENT(mozbrowserafterkeyup,
EventNameType_None, EventNameType_None,
eBeforeAfterKeyboardEventClass) eBeforeAfterKeyboardEventClass)
EVENT(loadeddata, EVENT(loadeddata,
NS_LOADEDDATA, eLoadedData,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(loadedmetadata, EVENT(loadedmetadata,
NS_LOADEDMETADATA, eLoadedMetaData,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(loadstart, EVENT(loadstart,
NS_LOADSTART, eLoadStart,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(mousedown, EVENT(mousedown,
@ -354,23 +354,23 @@ EVENT(lostpointercapture,
// Not supported yet; probably never because "wheel" is a better idea. // Not supported yet; probably never because "wheel" is a better idea.
// EVENT(mousewheel) // EVENT(mousewheel)
EVENT(pause, EVENT(pause,
NS_PAUSE, ePause,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(play, EVENT(play,
NS_PLAY, ePlay,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(playing, EVENT(playing,
NS_PLAYING, ePlaying,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(progress, EVENT(progress,
NS_PROGRESS, eProgress,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(ratechange, EVENT(ratechange,
NS_RATECHANGE, eRateChange,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(reset, EVENT(reset,
@ -378,11 +378,11 @@ EVENT(reset,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eBasicEventClass) eBasicEventClass)
EVENT(seeked, EVENT(seeked,
NS_SEEKED, eSeeked,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(seeking, EVENT(seeking,
NS_SEEKING, eSeeking,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(select, EVENT(select,
@ -394,7 +394,7 @@ EVENT(show,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(stalled, EVENT(stalled,
NS_STALLED, eStalled,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(submit, EVENT(submit,
@ -402,19 +402,19 @@ EVENT(submit,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eBasicEventClass) eBasicEventClass)
EVENT(suspend, EVENT(suspend,
NS_SUSPEND, eSuspend,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(timeupdate, EVENT(timeupdate,
NS_TIMEUPDATE, eTimeUpdate,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(volumechange, EVENT(volumechange,
NS_VOLUMECHANGE, eVolumeChange,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(waiting, EVENT(waiting,
NS_WAITING, eWaiting,
EventNameType_HTML, EventNameType_HTML,
eBasicEventClass) eBasicEventClass)
EVENT(wheel, EVENT(wheel,
@ -422,15 +422,15 @@ EVENT(wheel,
EventNameType_All, EventNameType_All,
eWheelEventClass) eWheelEventClass)
EVENT(copy, EVENT(copy,
NS_COPY, eCopy,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eClipboardEventClass) eClipboardEventClass)
EVENT(cut, EVENT(cut,
NS_CUT, eCut,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eClipboardEventClass) eClipboardEventClass)
EVENT(paste, EVENT(paste,
NS_PASTE, ePaste,
EventNameType_HTMLXUL, EventNameType_HTMLXUL,
eClipboardEventClass) eClipboardEventClass)
// Gecko-specific extensions that apply to elements // Gecko-specific extensions that apply to elements

View File

@ -743,7 +743,7 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
InitLineOrPageDelta(aTargetFrame, this, wheelEvent); InitLineOrPageDelta(aTargetFrame, this, wheelEvent);
} }
break; break;
case NS_SELECTION_SET: case eSetSelection:
IMEStateManager::HandleSelectionEvent(aPresContext, GetFocusedContent(), IMEStateManager::HandleSelectionEvent(aPresContext, GetFocusedContent(),
aEvent->AsSelectionEvent()); aEvent->AsSelectionEvent());
break; break;

View File

@ -149,8 +149,8 @@ GetEventMessageName(EventMessage aMessage)
return "NS_COMPOSITION_COMMIT_AS_IS"; return "NS_COMPOSITION_COMMIT_AS_IS";
case NS_COMPOSITION_COMMIT: case NS_COMPOSITION_COMMIT:
return "NS_COMPOSITION_COMMIT"; return "NS_COMPOSITION_COMMIT";
case NS_SELECTION_SET: case eSetSelection:
return "NS_SELECTION_SET"; return "eSetSelection";
default: default:
return "unacceptable event message"; return "unacceptable event message";
} }

View File

@ -291,14 +291,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread()); mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
nsRefPtr<MediaDecoderStateMachine> self = this; mMediaSink = CreateAudioSink();
auto audioSinkCreator = [self] () {
MOZ_ASSERT(self->OnTaskQueue());
return new DecodedAudioDataSink(
self->mAudioQueue, self->GetMediaTime(),
self->mInfo.mAudio, self->mDecoder->GetAudioChannel());
};
mAudioSink = new AudioSinkWrapper(mTaskQueue, audioSinkCreator);
} }
MediaDecoderStateMachine::~MediaDecoderStateMachine() MediaDecoderStateMachine::~MediaDecoderStateMachine()
@ -348,6 +341,19 @@ MediaDecoderStateMachine::InitializationTask()
SameOriginMediaChanged(); SameOriginMediaChanged();
} }
media::MediaSink*
MediaDecoderStateMachine::CreateAudioSink()
{
nsRefPtr<MediaDecoderStateMachine> self = this;
auto audioSinkCreator = [self] () {
MOZ_ASSERT(self->OnTaskQueue());
return new DecodedAudioDataSink(
self->mAudioQueue, self->GetMediaTime(),
self->mInfo.mAudio, self->mDecoder->GetAudioChannel());
};
return new AudioSinkWrapper(mTaskQueue, audioSinkCreator);
}
bool MediaDecoderStateMachine::HasFutureAudio() bool MediaDecoderStateMachine::HasFutureAudio()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
@ -377,7 +383,7 @@ int64_t MediaDecoderStateMachine::GetDecodedAudioDuration()
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
int64_t audioDecoded = AudioQueue().Duration(); int64_t audioDecoded = AudioQueue().Duration();
if (mAudioSink->IsStarted()) { if (mMediaSink->IsStarted()) {
audioDecoded += AudioEndTime() - GetMediaTime(); audioDecoded += AudioEndTime() - GetMediaTime();
} }
return audioDecoded; return audioDecoded;
@ -387,7 +393,6 @@ void MediaDecoderStateMachine::DiscardStreamData()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
MOZ_ASSERT(!mAudioSink->IsStarted(), "Should've been stopped in RunStateMachine()");
const auto clockTime = GetClock(); const auto clockTime = GetClock();
while (true) { while (true) {
@ -1077,8 +1082,7 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
SetPlayStartTime(TimeStamp::Now()); SetPlayStartTime(TimeStamp::Now());
MOZ_ASSERT(IsPlaying()); MOZ_ASSERT(IsPlaying());
StartAudioSink(); StartMediaSink();
StartDecodedStream();
DispatchDecodeTasksIfNeeded(); DispatchDecodeTasksIfNeeded();
} }
@ -1152,8 +1156,7 @@ void MediaDecoderStateMachine::VolumeChanged()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mAudioSink->SetVolume(mVolume); mMediaSink->SetVolume(mVolume);
mStreamSink->SetVolume(mVolume);
} }
void MediaDecoderStateMachine::RecomputeDuration() void MediaDecoderStateMachine::RecomputeDuration()
@ -1273,7 +1276,7 @@ void MediaDecoderStateMachine::Shutdown()
Reset(); Reset();
mAudioSink->Shutdown(); mMediaSink->Shutdown();
// Shut down our start time rendezvous. // Shut down our start time rendezvous.
if (mStartTimeRendezvous) { if (mStartTimeRendezvous) {
@ -1466,15 +1469,15 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
return mPendingSeek.mPromise.Ensure(__func__); return mPendingSeek.mPromise.Ensure(__func__);
} }
void MediaDecoderStateMachine::StopAudioSink() void MediaDecoderStateMachine::StopMediaSink()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mAudioSink->IsStarted()) { if (mMediaSink->IsStarted()) {
DECODER_LOG("Stop AudioSink"); DECODER_LOG("Stop MediaSink");
mAudioSink->Stop(); mMediaSink->Stop();
mAudioSinkPromise.DisconnectIfExists(); mMediaSinkPromise.DisconnectIfExists();
} }
} }
@ -1752,59 +1755,25 @@ MediaDecoderStateMachine::RequestVideoData()
} }
void void
MediaDecoderStateMachine::StartAudioSink() MediaDecoderStateMachine::StartMediaSink()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mAudioCaptured) {
MOZ_ASSERT(!mAudioSink->IsStarted());
return;
}
if (!mAudioSink->IsStarted()) { if (!mMediaSink->IsStarted()) {
mAudioCompleted = false; mAudioCompleted = false;
mAudioSink->Start(GetMediaTime(), mInfo); mMediaSink->Start(GetMediaTime(), mInfo);
auto promise = mAudioSink->OnEnded(TrackInfo::kAudioTrack); auto promise = mMediaSink->OnEnded(TrackInfo::kAudioTrack);
if (promise) { if (promise) {
mAudioSinkPromise.Begin(promise->Then( mMediaSinkPromise.Begin(promise->Then(
OwnerThread(), __func__, this, OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioSinkComplete, &MediaDecoderStateMachine::OnMediaSinkComplete,
&MediaDecoderStateMachine::OnAudioSinkError)); &MediaDecoderStateMachine::OnMediaSinkError));
} }
} }
} }
void
MediaDecoderStateMachine::StopDecodedStream()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mStreamSink->IsStarted()) {
mStreamSink->Stop();
mDecodedStreamPromise.DisconnectIfExists();
}
}
void
MediaDecoderStateMachine::StartDecodedStream()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
// Tell DecodedStream to start playback with specified start time and media
// info. This is consistent with how we create AudioSink in StartAudioThread().
if (mAudioCaptured && !mStreamSink->IsStarted()) {
mStreamSink->Start(GetMediaTime(), mInfo);
mDecodedStreamPromise.Begin(
mStreamSink->OnEnded(TrackInfo::kAudioTrack)->Then(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnDecodedStreamFinish,
&MediaDecoderStateMachine::OnDecodedStreamError));
}
}
int64_t MediaDecoderStateMachine::AudioDecodedUsecs() int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
@ -1813,7 +1782,7 @@ int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
// The amount of audio we have decoded is the amount of audio data we've // The amount of audio we have decoded is the amount of audio data we've
// already decoded and pushed to the hardware, plus the amount of audio // already decoded and pushed to the hardware, plus the amount of audio
// data waiting to be pushed to the hardware. // data waiting to be pushed to the hardware.
int64_t pushed = mAudioSink->IsStarted() ? (AudioEndTime() - GetMediaTime()) : 0; int64_t pushed = mMediaSink->IsStarted() ? (AudioEndTime() - GetMediaTime()) : 0;
// Currently for real time streams, AudioQueue().Duration() produce // Currently for real time streams, AudioQueue().Duration() produce
// wrong values (Bug 1114434), so we use frame counts to calculate duration. // wrong values (Bug 1114434), so we use frame counts to calculate duration.
@ -1842,7 +1811,7 @@ bool MediaDecoderStateMachine::OutOfDecodedAudio()
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
return IsAudioDecoding() && !AudioQueue().IsFinished() && return IsAudioDecoding() && !AudioQueue().IsFinished() &&
AudioQueue().GetSize() == 0 && AudioQueue().GetSize() == 0 &&
!mAudioSink->HasUnplayedFrames(TrackInfo::kAudioTrack); !mMediaSink->HasUnplayedFrames(TrackInfo::kAudioTrack);
} }
bool MediaDecoderStateMachine::HasLowUndecodedData() bool MediaDecoderStateMachine::HasLowUndecodedData()
@ -2416,8 +2385,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
mSentPlaybackEndedEvent = true; mSentPlaybackEndedEvent = true;
// MediaSink::GetEndTime() must be called before stopping playback. // MediaSink::GetEndTime() must be called before stopping playback.
StopAudioSink(); StopMediaSink();
StopDecodedStream();
} }
return NS_OK; return NS_OK;
@ -2443,11 +2411,10 @@ MediaDecoderStateMachine::Reset()
mState == DECODER_STATE_DORMANT || mState == DECODER_STATE_DORMANT ||
mState == DECODER_STATE_DECODING_NONE); mState == DECODER_STATE_DECODING_NONE);
// Stop the audio thread. Otherwise, AudioSink might be accessing AudioQueue // Stop the audio thread. Otherwise, MediaSink might be accessing AudioQueue
// outside of the decoder monitor while we are clearing the queue and causes // outside of the decoder monitor while we are clearing the queue and causes
// crash for no samples to be popped. // crash for no samples to be popped.
StopAudioSink(); StopMediaSink();
StopDecodedStream();
mVideoFrameEndTime = -1; mVideoFrameEndTime = -1;
mDecodedVideoEndTime = -1; mDecodedVideoEndTime = -1;
@ -2585,11 +2552,7 @@ int64_t MediaDecoderStateMachine::GetClock(TimeStamp* aTimeStamp) const
if (!IsPlaying()) { if (!IsPlaying()) {
clock_time = mPlayDuration; clock_time = mPlayDuration;
} else { } else {
if (mAudioCaptured) { clock_time = mMediaSink->GetPosition(&t);
clock_time = mStreamSink->GetPosition(&t);
} else {
clock_time = mAudioSink->GetPosition(&t);
}
NS_ASSERTION(GetMediaTime() <= clock_time, "Clock should go forwards."); NS_ASSERTION(GetMediaTime() <= clock_time, "Clock should go forwards.");
} }
if (aTimeStamp) { if (aTimeStamp) {
@ -2879,9 +2842,7 @@ void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp)
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
mPlayStartTime = aTimeStamp; mPlayStartTime = aTimeStamp;
mMediaSink->SetPlaying(!mPlayStartTime.IsNull());
mAudioSink->SetPlaying(!mPlayStartTime.IsNull());
mStreamSink->SetPlaying(!mPlayStartTime.IsNull());
} }
void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder() void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
@ -2959,7 +2920,7 @@ MediaDecoderStateMachine::LogicalPlaybackRateChanged()
} }
mPlaybackRate = mLogicalPlaybackRate; mPlaybackRate = mLogicalPlaybackRate;
mAudioSink->SetPlaybackRate(mPlaybackRate); mMediaSink->SetPlaybackRate(mPlaybackRate);
ScheduleStateMachine(); ScheduleStateMachine();
} }
@ -2968,7 +2929,7 @@ void MediaDecoderStateMachine::PreservesPitchChanged()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mAudioSink->SetPreservesPitch(mPreservesPitch); mMediaSink->SetPreservesPitch(mPreservesPitch);
} }
bool MediaDecoderStateMachine::IsShutdown() bool MediaDecoderStateMachine::IsShutdown()
@ -2982,33 +2943,33 @@ MediaDecoderStateMachine::AudioEndTime() const
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mAudioSink->IsStarted()) { if (mMediaSink->IsStarted()) {
return mAudioSink->GetEndTime(TrackInfo::kAudioTrack); return mMediaSink->GetEndTime(TrackInfo::kAudioTrack);
} else if (mAudioCaptured) {
return mStreamSink->GetEndTime(TrackInfo::kAudioTrack);
} }
MOZ_ASSERT(!HasAudio()); MOZ_ASSERT(!HasAudio());
return -1; return -1;
} }
void MediaDecoderStateMachine::OnAudioSinkComplete() void MediaDecoderStateMachine::OnMediaSinkComplete()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete(); mMediaSinkPromise.Complete();
mAudioCompleted = true; // Set true only when we have audio.
mAudioCompleted = mInfo.HasAudio();
// To notify PlaybackEnded as soon as possible.
ScheduleStateMachine();
} }
void MediaDecoderStateMachine::OnAudioSinkError() void MediaDecoderStateMachine::OnMediaSinkError()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete(); mMediaSinkPromise.Complete();
mAudioCompleted = true; // Set true only when we have audio.
mAudioCompleted = mInfo.HasAudio();
// Make the best effort to continue playback when there is video. // Make the best effort to continue playback when there is video.
if (HasVideo()) { if (HasVideo()) {
@ -3021,31 +2982,41 @@ void MediaDecoderStateMachine::OnAudioSinkError()
} }
void void
MediaDecoderStateMachine::OnDecodedStreamFinish() MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(mAudioCaptured, "Audio should be captured.");
mDecodedStreamPromise.Complete(); if (aCaptured == mAudioCaptured) {
if (mInfo.HasAudio()) { return;
mAudioCompleted = true;
} }
// To notify PlaybackEnded as soon as possible.
// Backup current playback parameters.
MediaSink::PlaybackParams params = mMediaSink->GetPlaybackParams();
// Stop and shut down the existing sink.
StopMediaSink();
mMediaSink->Shutdown();
// Create a new sink according to whether audio is captured.
// TODO: We can't really create a new DecodedStream until OutputStreamManager
// is extracted. It is tricky that the implementation of DecodedStream
// happens to allow reuse after shutdown without creating a new one.
mMediaSink = aCaptured ? mStreamSink : CreateAudioSink();
// Restore playback parameters.
mMediaSink->SetPlaybackParams(params);
// Start the sink if we are already playing. Otherwise it will be
// handled in MaybeStartPlayback().
if (IsPlaying()) {
StartMediaSink();
}
mAudioCaptured = aCaptured;
ScheduleStateMachine(); ScheduleStateMachine();
} }
void
MediaDecoderStateMachine::OnDecodedStreamError()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(mAudioCaptured, "Audio should be captured.");
mDecodedStreamPromise.Complete();
DecodeError();
}
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
@ -3055,55 +3026,15 @@ uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
: std::max<uint32_t>(sVideoQueueDefaultSize, MIN_VIDEO_QUEUE_SIZE); : std::max<uint32_t>(sVideoQueueDefaultSize, MIN_VIDEO_QUEUE_SIZE);
} }
void MediaDecoderStateMachine::DispatchAudioCaptured()
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
{
MOZ_ASSERT(self->OnTaskQueue());
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
if (!self->mAudioCaptured) {
// Stop the audio sink if it's running.
self->StopAudioSink();
self->mAudioCaptured = true;
// Start DecodedStream if we are already playing. Otherwise it will be
// handled in MaybeStartPlayback().
if (self->IsPlaying()) {
self->StartDecodedStream();
}
self->ScheduleStateMachine();
}
});
OwnerThread()->Dispatch(r.forget());
}
void MediaDecoderStateMachine::DispatchAudioUncaptured()
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
{
MOZ_ASSERT(self->OnTaskQueue());
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
if (self->mAudioCaptured) {
self->StopDecodedStream();
// Start again the audio sink.
self->mAudioCaptured = false;
if (self->IsPlaying()) {
self->StartAudioSink();
}
self->ScheduleStateMachine();
}
});
OwnerThread()->Dispatch(r.forget());
}
void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream, void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
bool aFinishWhenEnded) bool aFinishWhenEnded)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG("AddOutputStream aStream=%p!", aStream); DECODER_LOG("AddOutputStream aStream=%p!", aStream);
mStreamSink->AddOutput(aStream, aFinishWhenEnded); mStreamSink->AddOutput(aStream, aFinishWhenEnded);
DispatchAudioCaptured(); nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &MediaDecoderStateMachine::SetAudioCaptured, true);
OwnerThread()->Dispatch(r.forget());
} }
void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream) void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
@ -3112,7 +3043,9 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
DECODER_LOG("RemoveOutputStream=%p!", aStream); DECODER_LOG("RemoveOutputStream=%p!", aStream);
mStreamSink->RemoveOutput(aStream); mStreamSink->RemoveOutput(aStream);
if (!mStreamSink->HasConsumers()) { if (!mStreamSink->HasConsumers()) {
DispatchAudioUncaptured(); nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &MediaDecoderStateMachine::SetAudioCaptured, false);
OwnerThread()->Dispatch(r.forget());
} }
} }

View File

@ -167,8 +167,7 @@ private:
// constructor immediately after the task queue is created. // constructor immediately after the task queue is created.
void InitializationTask(); void InitializationTask();
void DispatchAudioCaptured(); void SetAudioCaptured(bool aCaptured);
void DispatchAudioUncaptured();
void Shutdown(); void Shutdown();
public: public:
@ -489,19 +488,17 @@ protected:
// state machine thread. // state machine thread.
void UpdateRenderedVideoFrames(); void UpdateRenderedVideoFrames();
// Stops the audio sink and shut it down. media::MediaSink* CreateAudioSink();
// Stops the media sink and shut it down.
// The decoder monitor must be held with exactly one lock count. // The decoder monitor must be held with exactly one lock count.
// Called on the state machine thread. // Called on the state machine thread.
void StopAudioSink(); void StopMediaSink();
// Create and start the audio sink. // Create and start the media sink.
// The decoder monitor must be held with exactly one lock count. // The decoder monitor must be held with exactly one lock count.
// Called on the state machine thread. // Called on the state machine thread.
void StartAudioSink(); void StartMediaSink();
void StopDecodedStream();
void StartDecodedStream();
// Notification method invoked when mPlayState changes. // Notification method invoked when mPlayState changes.
void PlayStateChanged(); void PlayStateChanged();
@ -648,16 +645,12 @@ protected:
void SetPlayStartTime(const TimeStamp& aTimeStamp); void SetPlayStartTime(const TimeStamp& aTimeStamp);
private: private:
// Resolved by the AudioSink to signal that all outstanding work is complete // Resolved by the MediaSink to signal that all outstanding work is complete
// and the sink is shutting down. // and the sink is shutting down.
void OnAudioSinkComplete(); void OnMediaSinkComplete();
// Rejected by the AudioSink to signal errors. // Rejected by the MediaSink to signal errors.
void OnAudioSinkError(); void OnMediaSinkError();
void OnDecodedStreamFinish();
void OnDecodedStreamError();
// Return true if the video decoder's decode speed can not catch up the // Return true if the video decoder's decode speed can not catch up the
// play time. // play time.
@ -977,15 +970,15 @@ private:
// Media Fragment end time in microseconds. Access controlled by decoder monitor. // Media Fragment end time in microseconds. Access controlled by decoder monitor.
int64_t mFragmentEndTime; int64_t mFragmentEndTime;
// The audio sink resource. Used on the state machine thread. // The media sink resource. Used on the state machine thread.
nsRefPtr<media::MediaSink> mAudioSink; nsRefPtr<media::MediaSink> mMediaSink;
// The reader, don't call its methods with the decoder monitor held. // The reader, don't call its methods with the decoder monitor held.
// This is created in the state machine's constructor. // This is created in the state machine's constructor.
nsRefPtr<MediaDecoderReader> mReader; nsRefPtr<MediaDecoderReader> mReader;
// The end time of the last audio frame that's been pushed onto the audio sink // The end time of the last audio frame that's been pushed onto the media sink
// or DecodedStream in microseconds. This will approximately be the end time // in microseconds. This will approximately be the end time
// of the audio stream, unless another frame is pushed to the hardware. // of the audio stream, unless another frame is pushed to the hardware.
int64_t AudioEndTime() const; int64_t AudioEndTime() const;
@ -1270,8 +1263,7 @@ private:
// Media data resource from the decoder. // Media data resource from the decoder.
nsRefPtr<MediaResource> mResource; nsRefPtr<MediaResource> mResource;
MozPromiseRequestHolder<GenericPromise> mAudioSinkPromise; MozPromiseRequestHolder<GenericPromise> mMediaSinkPromise;
MozPromiseRequestHolder<GenericPromise> mDecodedStreamPromise;
MediaEventListener mAudioQueueListener; MediaEventListener mAudioQueueListener;
MediaEventListener mVideoQueueListener; MediaEventListener mVideoQueueListener;

View File

@ -12,7 +12,7 @@
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
// Turn off the authentication dialog blocking for this test. // Turn off the authentication dialog blocking for this test.
SpecialPowers.setIntPref("network.auth.allow-subresource-auth", 2) SpecialPowers.setIntPref("network.auth.subresource-http-auth-allow", 2)
var tests = [ var tests = [
// Not the same origin no CORS asked for, should have silence // Not the same origin no CORS asked for, should have silence

View File

@ -36,6 +36,9 @@
#include "WorkerPrivate.h" #include "WorkerPrivate.h"
#include "WorkerRunnable.h" #include "WorkerRunnable.h"
#include "xpcpublic.h" #include "xpcpublic.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -536,10 +539,10 @@ Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32()); PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32());
if (task == PromiseCallback::Resolve) { if (task == PromiseCallback::Resolve) {
promise->MaybeResolveInternal(aCx, args.get(0));
if (!promise->CaptureStack(aCx, promise->mFullfillmentStack)) { if (!promise->CaptureStack(aCx, promise->mFullfillmentStack)) {
return false; return false;
} }
promise->MaybeResolveInternal(aCx, args.get(0));
} else { } else {
promise->MaybeRejectInternal(aCx, args.get(0)); promise->MaybeRejectInternal(aCx, args.get(0));
if (!promise->CaptureStack(aCx, promise->mRejectionStack)) { if (!promise->CaptureStack(aCx, promise->mRejectionStack)) {
@ -1342,6 +1345,29 @@ Promise::RejectInternal(JSContext* aCx,
void void
Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState) Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
{ {
#ifdef MOZ_CRASHREPORTER
if (!mGlobal && mFullfillmentStack) {
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::RootedObject stack(cx, mFullfillmentStack);
JSAutoCompartment ac(cx, stack);
JS::RootedString stackJSString(cx);
if (JS::BuildStackString(cx, stack, &stackJSString)) {
nsAutoJSString stackString;
if (stackString.init(cx, stackJSString)) {
// Put the string in the crash report here, since we're about to crash
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("cced_promise_stack"),
NS_ConvertUTF16toUTF8(stackString));
} else {
JS_ClearPendingException(cx);
}
} else {
JS_ClearPendingException(cx);
}
}
#endif
if (mGlobal->IsDying()) { if (mGlobal->IsDying()) {
return; return;
} }

View File

@ -628,7 +628,6 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
// The "Access-Control-Allow-Headers" header contains a comma separated // The "Access-Control-Allow-Headers" header contains a comma separated
// list of header names. // list of header names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"), http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
headerVal); headerVal);
nsTArray<nsCString> headers; nsTArray<nsCString> headers;
@ -1130,7 +1129,6 @@ nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
// The "Access-Control-Allow-Methods" header contains a comma separated // The "Access-Control-Allow-Methods" header contains a comma separated
// list of method names. // list of method names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"), http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
headerVal); headerVal);
@ -1161,7 +1159,6 @@ nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
// The "Access-Control-Allow-Headers" header contains a comma separated // The "Access-Control-Allow-Headers" header contains a comma separated
// list of method names. // list of method names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"), http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
headerVal); headerVal);

View File

@ -0,0 +1,28 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GeolocationUtil.h"
double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon)
{
// Use spherical law of cosines to calculate difference
// Not quite as correct as the Haversine but simpler and cheaper
const double radsInDeg = M_PI / 180.0;
const double rNewLat = aLat * radsInDeg;
const double rNewLon = aLon * radsInDeg;
const double rOldLat = aLastLat * radsInDeg;
const double rOldLon = aLastLon * radsInDeg;
// WGS84 equatorial radius of earth = 6378137m
double cosDelta = (sin(rNewLat) * sin(rOldLat)) +
(cos(rNewLat) * cos(rOldLat) * cos(rOldLon - rNewLon));
if (cosDelta > 1.0) {
cosDelta = 1.0;
} else if (cosDelta < -1.0) {
cosDelta = -1.0;
}
return acos(cosDelta) * 6378137;
}

View File

@ -0,0 +1,13 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GEOLOCATIONUTIL_H
#define GEOLOCATIONUTIL_H
double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon);
#endif

View File

@ -20,6 +20,8 @@
#include <pthread.h> #include <pthread.h>
#include <hardware/gps.h> #include <hardware/gps.h>
#include "GeolocationUtil.h"
#include "mozstumbler/MozStumbler.h"
#include "mozilla/Constants.h" #include "mozilla/Constants.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
@ -88,71 +90,6 @@ AGpsCallbacks GonkGPSGeolocationProvider::mAGPSCallbacks;
AGpsRilCallbacks GonkGPSGeolocationProvider::mAGPSRILCallbacks; AGpsRilCallbacks GonkGPSGeolocationProvider::mAGPSRILCallbacks;
#endif // MOZ_B2G_RIL #endif // MOZ_B2G_RIL
double CalculateDeltaInMeter(double aLat, double aLon, double aLastLat, double aLastLon)
{
// Use spherical law of cosines to calculate difference
// Not quite as correct as the Haversine but simpler and cheaper
const double radsInDeg = M_PI / 180.0;
const double rNewLat = aLat * radsInDeg;
const double rNewLon = aLon * radsInDeg;
const double rOldLat = aLastLat * radsInDeg;
const double rOldLon = aLastLon * radsInDeg;
// WGS84 equatorial radius of earth = 6378137m
double cosDelta = (sin(rNewLat) * sin(rOldLat)) +
(cos(rNewLat) * cos(rOldLat) * cos(rOldLon - rNewLon));
if (cosDelta > 1.0) {
cosDelta = 1.0;
} else if (cosDelta < -1.0) {
cosDelta = -1.0;
}
return acos(cosDelta) * 6378137;
}
class RequestCellInfoEvent : public nsRunnable {
public:
RequestCellInfoEvent(StumblerInfo *callback)
: mRequestCallback(callback)
{}
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread());
// Get Cell Info
nsCOMPtr<nsIMobileConnectionService> service =
do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
if (!service) {
nsContentUtils::LogMessageToConsole("Stumbler-can not get nsIMobileConnectionService \n");
return NS_OK;
}
nsCOMPtr<nsIMobileConnection> connection;
uint32_t numberOfRilServices = 1, cellInfoNum = 0;
service->GetNumItems(&numberOfRilServices);
for (uint32_t rilNum = 0; rilNum < numberOfRilServices; rilNum++) {
service->GetItemByServiceId(rilNum /* Client Id */, getter_AddRefs(connection));
if (!connection) {
nsContentUtils::LogMessageToConsole("Stumbler-can not get nsIMobileConnection by ServiceId %d \n", rilNum);
} else {
cellInfoNum++;
connection->GetCellInfoList(mRequestCallback);
}
}
mRequestCallback->SetCellInfoResponsesExpected(cellInfoNum);
// Get Wifi AP Info
nsCOMPtr<nsIInterfaceRequestor> ir = do_GetService("@mozilla.org/telephony/system-worker-manager;1");
nsCOMPtr<nsIWifi> wifi = do_GetInterface(ir);
if (!wifi) {
mRequestCallback->SetWifiInfoResponseReceived();
nsContentUtils::LogMessageToConsole("Stumbler-can not get nsIWifi interface\n");
return NS_OK;
}
wifi->GetWifiScanResults(mRequestCallback);
return NS_OK;
}
private:
nsRefPtr<StumblerInfo> mRequestCallback;
};
void void
GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location) GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
@ -211,35 +148,7 @@ GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
nsRefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere); nsRefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
NS_DispatchToMainThread(event); NS_DispatchToMainThread(event);
const double kMinChangeInMeters = 30; MozStumble(somewhere);
static int64_t lastTime_ms = 0;
static double sLastLat = 0;
static double sLastLon = 0;
double delta = -1.0;
int64_t timediff = (PR_Now() / PR_USEC_PER_MSEC) - lastTime_ms;
if (0 != sLastLon || 0 != sLastLat) {
delta = CalculateDeltaInMeter(location->latitude, location->longitude, sLastLat, sLastLon);
}
if (gDebug_isLoggingEnabled) {
nsContentUtils::LogMessageToConsole("Stumbler-Location. [%f , %f] time_diff:%lld, delta : %f\n",
location->longitude, location->latitude, timediff, delta);
}
// Consecutive GPS locations must be 30 meters and 3 seconds apart
if (lastTime_ms == 0 || ((timediff >= STUMBLE_INTERVAL_MS) && (delta > kMinChangeInMeters))){
lastTime_ms = (PR_Now() / PR_USEC_PER_MSEC);
sLastLat = location->latitude;
sLastLon = location->longitude;
nsRefPtr<StumblerInfo> requestCallback = new StumblerInfo(somewhere);
nsRefPtr<RequestCellInfoEvent> runnable = new RequestCellInfoEvent(requestCallback);
NS_DispatchToMainThread(runnable);
} else {
if (gDebug_isLoggingEnabled) {
nsContentUtils::LogMessageToConsole(
"Stumbler-GPS locations less than 30 meters and 3 seconds. Ignore!\n");
}
}
} }
void void

View File

@ -33,6 +33,7 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'dom_system_gonk' XPIDL_MODULE = 'dom_system_gonk'
EXPORTS += [ EXPORTS += [
'GeolocationUtil.h',
'GonkGPSGeolocationProvider.h', 'GonkGPSGeolocationProvider.h',
'mozstumbler/MozStumbler.h', 'mozstumbler/MozStumbler.h',
'nsVolume.h', 'nsVolume.h',
@ -43,6 +44,7 @@ UNIFIED_SOURCES += [
'AudioManager.cpp', 'AudioManager.cpp',
'AutoMounter.cpp', 'AutoMounter.cpp',
'AutoMounterSetting.cpp', 'AutoMounterSetting.cpp',
'GeolocationUtil.cpp',
'GonkGPSGeolocationProvider.cpp', 'GonkGPSGeolocationProvider.cpp',
'MozMtpDatabase.cpp', 'MozMtpDatabase.cpp',
'MozMtpServer.cpp', 'MozMtpServer.cpp',

View File

@ -5,12 +5,22 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MozStumbler.h" #include "MozStumbler.h"
#include "nsDataHashtable.h"
#include "nsGeoPosition.h" #include "nsGeoPosition.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "StumblerLogging.h" #include "StumblerLogging.h"
#include "WriteStumbleOnThread.h" #include "WriteStumbleOnThread.h"
#include "nsNetCID.h" #include "../GeolocationUtil.h"
#include "nsDataHashtable.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIMobileConnectionInfo.h"
#include "nsIMobileConnectionService.h"
#include "nsIMobileCellInfo.h"
#include "nsIMobileNetworkInfo.h"
#include "nsINetworkInterface.h"
#include "nsIRadioInterfaceLayer.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -18,6 +28,101 @@ using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(StumblerInfo, nsICellInfoListCallback, nsIWifiScanResultsReady) NS_IMPL_ISUPPORTS(StumblerInfo, nsICellInfoListCallback, nsIWifiScanResultsReady)
class RequestCellInfoEvent : public nsRunnable {
public:
RequestCellInfoEvent(StumblerInfo *callback)
: mRequestCallback(callback)
{}
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread());
// Get Cell Info
nsCOMPtr<nsIMobileConnectionService> service =
do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
if (!service) {
STUMBLER_ERR("Stumbler-can not get nsIMobileConnectionService \n");
return NS_OK;
}
nsCOMPtr<nsIMobileConnection> connection;
uint32_t numberOfRilServices = 1, cellInfoNum = 0;
service->GetNumItems(&numberOfRilServices);
for (uint32_t rilNum = 0; rilNum < numberOfRilServices; rilNum++) {
service->GetItemByServiceId(rilNum /* Client Id */, getter_AddRefs(connection));
if (!connection) {
STUMBLER_ERR("Stumbler-can not get nsIMobileConnection by ServiceId %d \n", rilNum);
} else {
cellInfoNum++;
connection->GetCellInfoList(mRequestCallback);
}
}
mRequestCallback->SetCellInfoResponsesExpected(cellInfoNum);
// Get Wifi AP Info
nsCOMPtr<nsIInterfaceRequestor> ir = do_GetService("@mozilla.org/telephony/system-worker-manager;1");
nsCOMPtr<nsIWifi> wifi = do_GetInterface(ir);
if (!wifi) {
mRequestCallback->SetWifiInfoResponseReceived();
STUMBLER_ERR("Stumbler-can not get nsIWifi interface\n");
return NS_OK;
}
wifi->GetWifiScanResults(mRequestCallback);
return NS_OK;
}
private:
nsRefPtr<StumblerInfo> mRequestCallback;
};
void
MozStumble(nsGeoPosition* position)
{
if (WriteStumbleOnThread::IsFileWaitingForUpload()) {
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT(target);
// Knowing that file is waiting to upload, and no collection will take place,
// just trigger the thread with an empty string.
nsCOMPtr<nsIRunnable> event = new WriteStumbleOnThread(EmptyCString());
target->Dispatch(event, NS_DISPATCH_NORMAL);
return;
}
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
position->GetCoords(getter_AddRefs(coords));
if (!coords) {
return;
}
double latitude, longitude;
coords->GetLatitude(&latitude);
coords->GetLongitude(&longitude);
const double kMinChangeInMeters = 30;
static int64_t lastTime_ms = 0;
static double sLastLat = 0;
static double sLastLon = 0;
double delta = -1.0;
int64_t timediff = (PR_Now() / PR_USEC_PER_MSEC) - lastTime_ms;
if (0 != sLastLon || 0 != sLastLat) {
delta = CalculateDeltaInMeter(latitude, longitude, sLastLat, sLastLon);
}
STUMBLER_DBG("Stumbler-Location. [%f , %f] time_diff:%lld, delta : %f\n",
longitude, latitude, timediff, delta);
// Consecutive GPS locations must be 30 meters and 3 seconds apart
if (lastTime_ms == 0 || ((timediff >= STUMBLE_INTERVAL_MS) && (delta > kMinChangeInMeters))){
lastTime_ms = (PR_Now() / PR_USEC_PER_MSEC);
sLastLat = latitude;
sLastLon = longitude;
nsRefPtr<StumblerInfo> requestCallback = new StumblerInfo(position);
nsRefPtr<RequestCellInfoEvent> runnable = new RequestCellInfoEvent(requestCallback);
NS_DispatchToMainThread(runnable);
} else {
STUMBLER_DBG("Stumbler-GPS locations less than 30 meters and 3 seconds. Ignore!\n");
}
}
void void
StumblerInfo::SetWifiInfoResponseReceived() StumblerInfo::SetWifiInfoResponseReceived()
{ {

View File

@ -15,6 +15,8 @@
class nsGeoPosition; class nsGeoPosition;
void MozStumble(nsGeoPosition* position);
class StumblerInfo final : public nsICellInfoListCallback, class StumblerInfo final : public nsICellInfoListCallback,
public nsIWifiScanResultsReady public nsIWifiScanResultsReady
{ {

View File

@ -7,14 +7,15 @@
#include "UploadStumbleRunnable.h" #include "UploadStumbleRunnable.h"
#include "StumblerLogging.h" #include "StumblerLogging.h"
#include "mozilla/dom/Event.h" #include "mozilla/dom/Event.h"
#include "nsIInputStream.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsIURLFormatter.h" #include "nsIURLFormatter.h"
#include "nsIVariant.h" #include "nsIVariant.h"
#include "nsIXMLHttpRequest.h" #include "nsIXMLHttpRequest.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
UploadStumbleRunnable::UploadStumbleRunnable(const nsACString& aUploadData) UploadStumbleRunnable::UploadStumbleRunnable(nsIInputStream* aUploadData)
: mUploadData(aUploadData) : mUploadInputStream(aUploadData)
{ {
} }
@ -36,7 +37,7 @@ UploadStumbleRunnable::Upload()
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance("@mozilla.org/variant;1", &rv); nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance("@mozilla.org/variant;1", &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = variant->SetAsACString(mUploadData); rv = variant->SetAsISupports(mUploadInputStream);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXMLHttpRequest> xhr = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv); nsCOMPtr<nsIXMLHttpRequest> xhr = do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
@ -63,13 +64,13 @@ UploadStumbleRunnable::Upload()
rv = xhr->Open(NS_LITERAL_CSTRING("POST"), NS_ConvertUTF16toUTF8(url), false, EmptyString(), EmptyString()); rv = xhr->Open(NS_LITERAL_CSTRING("POST"), NS_ConvertUTF16toUTF8(url), false, EmptyString(), EmptyString());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
xhr->SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), NS_LITERAL_CSTRING("application/json")); xhr->SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), NS_LITERAL_CSTRING("gzip"));
xhr->SetMozBackgroundRequest(true); xhr->SetMozBackgroundRequest(true);
// 60s timeout // 60s timeout
xhr->SetTimeout(60 * 1000); xhr->SetTimeout(60 * 1000);
nsCOMPtr<EventTarget> target(do_QueryInterface(xhr)); nsCOMPtr<EventTarget> target(do_QueryInterface(xhr));
nsRefPtr<nsIDOMEventListener> listener = new UploadEventListener(xhr, mUploadData.Length()); nsRefPtr<nsIDOMEventListener> listener = new UploadEventListener(xhr);
const char* const sEventStrings[] = { const char* const sEventStrings[] = {
// nsIXMLHttpRequestEventTarget event types // nsIXMLHttpRequestEventTarget event types
@ -93,8 +94,8 @@ UploadStumbleRunnable::Upload()
NS_IMPL_ISUPPORTS(UploadEventListener, nsIDOMEventListener) NS_IMPL_ISUPPORTS(UploadEventListener, nsIDOMEventListener)
UploadEventListener::UploadEventListener(nsIXMLHttpRequest* aXHR, int64_t aFileSize) UploadEventListener::UploadEventListener(nsIXMLHttpRequest* aXHR)
: mXHR(aXHR), mFileSize(aFileSize) : mXHR(aXHR)
{ {
} }
@ -109,7 +110,7 @@ UploadEventListener::HandleEvent(nsIDOMEvent* aEvent)
} }
if (type.EqualsLiteral("load")) { if (type.EqualsLiteral("load")) {
STUMBLER_DBG("Got load Event : size %lld", mFileSize); STUMBLER_DBG("Got load Event\n");
} else if (type.EqualsLiteral("error") && mXHR) { } else if (type.EqualsLiteral("error") && mXHR) {
STUMBLER_ERR("Upload Error"); STUMBLER_ERR("Upload Error");
} else { } else {

View File

@ -11,6 +11,7 @@
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
class nsIXMLHttpRequest; class nsIXMLHttpRequest;
class nsIInputStream;
/* /*
This runnable is managed by WriteStumbleOnThread only, see that class This runnable is managed by WriteStumbleOnThread only, see that class
@ -19,12 +20,12 @@ class nsIXMLHttpRequest;
class UploadStumbleRunnable final : public nsRunnable class UploadStumbleRunnable final : public nsRunnable
{ {
public: public:
explicit UploadStumbleRunnable(const nsACString& aUploadData); explicit UploadStumbleRunnable(nsIInputStream* aUploadInputStream);
NS_IMETHOD Run() override; NS_IMETHOD Run() override;
private: private:
virtual ~UploadStumbleRunnable() {} virtual ~UploadStumbleRunnable() {}
const nsCString mUploadData; nsCOMPtr<nsIInputStream> mUploadInputStream;
nsresult Upload(); nsresult Upload();
}; };
@ -32,7 +33,7 @@ private:
class UploadEventListener : public nsIDOMEventListener class UploadEventListener : public nsIDOMEventListener
{ {
public: public:
UploadEventListener(nsIXMLHttpRequest* aXHR, int64_t aFileSize); UploadEventListener(nsIXMLHttpRequest* aXHR);
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER NS_DECL_NSIDOMEVENTLISTENER
@ -40,7 +41,6 @@ public:
protected: protected:
virtual ~UploadEventListener() {} virtual ~UploadEventListener() {}
nsCOMPtr<nsIXMLHttpRequest> mXHR; nsCOMPtr<nsIXMLHttpRequest> mXHR;
int64_t mFileSize;
}; };
#endif #endif

View File

@ -17,12 +17,12 @@
#define ONEDAY_IN_MSEC (24 * 60 * 60 * 1000) #define ONEDAY_IN_MSEC (24 * 60 * 60 * 1000)
#define MAX_UPLOAD_ATTEMPTS 20 #define MAX_UPLOAD_ATTEMPTS 20
mozilla::Atomic<bool> WriteStumbleOnThread::sIsUploading(false); mozilla::Atomic<bool> WriteStumbleOnThread::sIsFileWaitingForUpload(false);
mozilla::Atomic<bool> WriteStumbleOnThread::sIsAlreadyRunning(false); mozilla::Atomic<bool> WriteStumbleOnThread::sIsAlreadyRunning(false);
WriteStumbleOnThread::UploadFreqGuard WriteStumbleOnThread::sUploadFreqGuard = {0}; WriteStumbleOnThread::UploadFreqGuard WriteStumbleOnThread::sUploadFreqGuard = {0};
#define FILENAME_INPROGRESS NS_LITERAL_CSTRING("stumbles.json") #define FILENAME_INPROGRESS NS_LITERAL_CSTRING("stumbles.json.gz")
#define FILENAME_COMPLETED NS_LITERAL_CSTRING("stumbles.done.json") #define FILENAME_COMPLETED NS_LITERAL_CSTRING("stumbles.done.json.gz")
#define OUTPUT_DIR NS_LITERAL_CSTRING("mozstumbler") #define OUTPUT_DIR NS_LITERAL_CSTRING("mozstumbler")
class DeleteRunnable : public nsRunnable class DeleteRunnable : public nsRunnable
@ -42,7 +42,8 @@ class DeleteRunnable : public nsRunnable
tmpFile->Remove(true); tmpFile->Remove(true);
} }
// critically, this sets this flag to false so writing can happen again // critically, this sets this flag to false so writing can happen again
WriteStumbleOnThread::sIsUploading = false; WriteStumbleOnThread::sIsAlreadyRunning = false;
WriteStumbleOnThread::sIsFileWaitingForUpload = false;
return NS_OK; return NS_OK;
} }
@ -50,11 +51,17 @@ class DeleteRunnable : public nsRunnable
~DeleteRunnable() {} ~DeleteRunnable() {}
}; };
bool
WriteStumbleOnThread::IsFileWaitingForUpload()
{
return sIsFileWaitingForUpload;
}
void void
WriteStumbleOnThread::UploadEnded(bool deleteUploadFile) WriteStumbleOnThread::UploadEnded(bool deleteUploadFile)
{ {
if (!deleteUploadFile) { if (!deleteUploadFile) {
sIsUploading = false; sIsAlreadyRunning = false;
return; return;
} }
@ -64,15 +71,6 @@ WriteStumbleOnThread::UploadEnded(bool deleteUploadFile)
target->Dispatch(event, NS_DISPATCH_NORMAL); target->Dispatch(event, NS_DISPATCH_NORMAL);
} }
#define DUMP(o, s) \
do { \
const char* s2 = (s); \
uint32_t dummy; \
nsresult rv = (o)->Write((s2), strlen(s2), &dummy); \
if (NS_WARN_IF(NS_FAILED(rv))) \
STUMBLER_ERR("write err"); \
} while (0)
void void
WriteStumbleOnThread::WriteJSON(Partition aPart) WriteStumbleOnThread::WriteJSON(Partition aPart)
{ {
@ -87,10 +85,10 @@ WriteStumbleOnThread::WriteJSON(Partition aPart)
return; return;
} }
nsCOMPtr<nsIFileOutputStream> ostream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); nsRefPtr<nsGZFileWriter> gzWriter = new nsGZFileWriter(nsGZFileWriter::Append);
rv = ostream->Init(tmpFile, PR_WRONLY | PR_APPEND, 0666, 0); rv = gzWriter->Init(tmpFile);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
STUMBLER_ERR("Open a file for stumble failed"); STUMBLER_ERR("gzWriter init failed");
return; return;
} }
@ -105,8 +103,8 @@ WriteStumbleOnThread::WriteJSON(Partition aPart)
// Need to add "]}" after the last item // Need to add "]}" after the last item
if (aPart == Partition::End) { if (aPart == Partition::End) {
DUMP(ostream, "]}"); gzWriter->Write("]}");
rv = ostream->Close(); rv = gzWriter->Finish();
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
STUMBLER_ERR("ostream finish failed"); STUMBLER_ERR("ostream finish failed");
} }
@ -136,14 +134,14 @@ WriteStumbleOnThread::WriteJSON(Partition aPart)
// Need to add "{items:[" before the first item // Need to add "{items:[" before the first item
if (aPart == Partition::Begining) { if (aPart == Partition::Begining) {
DUMP(ostream, "{\"items\":[{"); gzWriter->Write("{\"items\":[{");
} else if (aPart == Partition::Middle) { } else if (aPart == Partition::Middle) {
DUMP(ostream, ",{"); gzWriter->Write(",{");
} }
DUMP(ostream, mDesc.get()); gzWriter->Write(mDesc.get());
// one item is ended with '}' (e.g. {item}) // one item is ended with '}' (e.g. {item})
DUMP(ostream, "}"); gzWriter->Write("}");
rv = ostream->Close(); rv = gzWriter->Finish();
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
STUMBLER_ERR("ostream finish failed"); STUMBLER_ERR("ostream finish failed");
} }
@ -204,7 +202,9 @@ WriteStumbleOnThread::Run()
if (UploadFileStatus::NoFile != status) { if (UploadFileStatus::NoFile != status) {
if (UploadFileStatus::ExistsAndReadyToUpload == status) { if (UploadFileStatus::ExistsAndReadyToUpload == status) {
sIsFileWaitingForUpload = true;
Upload(); Upload();
return NS_OK;
} }
} else { } else {
Partition partition = GetWritePosition(); Partition partition = GetWritePosition();
@ -215,6 +215,7 @@ WriteStumbleOnThread::Run()
} }
} }
sIsFileWaitingForUpload = false;
sIsAlreadyRunning = false; sIsAlreadyRunning = false;
return NS_OK; return NS_OK;
} }
@ -259,11 +260,6 @@ WriteStumbleOnThread::Upload()
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
bool b = sIsUploading.exchange(true);
if (b) {
return;
}
time_t seconds = time(0); time_t seconds = time(0);
int day = seconds / (60 * 60 * 24); int day = seconds / (60 * 60 * 24);
@ -275,7 +271,7 @@ WriteStumbleOnThread::Upload()
sUploadFreqGuard.attempts++; sUploadFreqGuard.attempts++;
if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) { if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) {
STUMBLER_ERR("Too many upload attempts today"); STUMBLER_ERR("Too many upload attempts today");
sIsUploading = false; sIsAlreadyRunning = false;
return; return;
} }
@ -286,32 +282,23 @@ WriteStumbleOnThread::Upload()
rv = tmpFile->GetFileSize(&fileSize); rv = tmpFile->GetFileSize(&fileSize);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
STUMBLER_ERR("GetFileSize failed"); STUMBLER_ERR("GetFileSize failed");
sIsUploading = false; sIsAlreadyRunning = false;
return; return;
} }
if (fileSize <= 0) { if (fileSize <= 0) {
sIsUploading = false; sIsAlreadyRunning = false;
return; return;
} }
// prepare json into nsIInputStream // prepare json into nsIInputStream
nsCOMPtr<nsIInputStream> inStream; nsCOMPtr<nsIInputStream> inStream;
rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile, -1, -1, rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile);
nsIFileInputStream::DEFER_OPEN);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
sIsUploading = false; sIsAlreadyRunning = false;
return; return;
} }
nsCString bufStr; nsRefPtr<nsIRunnable> uploader = new UploadStumbleRunnable(inStream);
rv = NS_ReadInputStreamToString(inStream, bufStr, fileSize);
if (NS_FAILED(rv)) {
sIsUploading = false;
return;
}
nsRefPtr<nsIRunnable> uploader = new UploadStumbleRunnable(bufStr);
NS_DispatchToMainThread(uploader); NS_DispatchToMainThread(uploader);
} }

View File

@ -9,6 +9,8 @@
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
class DeleteRunnable;
/* /*
This class is the entry point to stumbling, in that it This class is the entry point to stumbling, in that it
receives the location+cell+wifi string and writes it receives the location+cell+wifi string and writes it
@ -43,10 +45,13 @@ public:
NS_IMETHODIMP Run() override; NS_IMETHODIMP Run() override;
static void UploadEnded(bool deleteUploadFile); static void UploadEnded(bool deleteUploadFile);
// Don't write while uploading is happening
static mozilla::Atomic<bool> sIsUploading; // Used externally to determine if cell+wifi scans should happen
// (returns false for that case).
static bool IsFileWaitingForUpload();
private: private:
friend class DeleteRunnable;
enum class Partition { enum class Partition {
Begining, Begining,
@ -71,6 +76,8 @@ private:
// Only run one instance of this // Only run one instance of this
static mozilla::Atomic<bool> sIsAlreadyRunning; static mozilla::Atomic<bool> sIsAlreadyRunning;
static mozilla::Atomic<bool> sIsFileWaitingForUpload;
// Limit the upload attempts per day. If the device is rebooted // Limit the upload attempts per day. If the device is rebooted
// this resets the allowed attempts, which is acceptable. // this resets the allowed attempts, which is acceptable.
struct UploadFreqGuard { struct UploadFreqGuard {

View File

@ -49,8 +49,8 @@ enum vCardProperties
* objects. * objects.
*/ */
enum vCardOrderType { enum vCardOrderType {
"alphabetical",
"indexed", // default "indexed", // default
"alphabetical",
"phonetical" "phonetical"
}; };

View File

@ -27,7 +27,7 @@ interface PushManager {
[ChromeOnly, Throws, Exposed=Window] [ChromeOnly, Throws, Exposed=Window]
void setPushManagerImpl(PushManagerImpl store); void setPushManagerImpl(PushManagerImpl store);
[Throws] [Throws, UseCounter]
Promise<PushSubscription> subscribe(); Promise<PushSubscription> subscribe();
[Throws] [Throws]
Promise<PushSubscription?> getSubscription(); Promise<PushSubscription?> getSubscription();

View File

@ -14,7 +14,7 @@ interface Principal;
interface PushSubscription interface PushSubscription
{ {
readonly attribute USVString endpoint; readonly attribute USVString endpoint;
[Throws] [Throws, UseCounter]
Promise<boolean> unsubscribe(); Promise<boolean> unsubscribe();
jsonifier; jsonifier;

View File

@ -1323,8 +1323,9 @@ bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType) NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType)
{ {
if (!FireClipboardEvent(NS_PASTE, aSelectionType)) if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK; return NS_OK;
}
// Get Clipboard Service // Get Clipboard Service
nsresult rv; nsresult rv;
@ -1406,8 +1407,9 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
{ {
// Use an invalid value for the clipboard type as data comes from aTransferable // Use an invalid value for the clipboard type as data comes from aTransferable
// and we don't currently implement a way to put that in the data transfer yet. // and we don't currently implement a way to put that in the data transfer yet.
if (!FireClipboardEvent(NS_PASTE, nsIClipboard::kGlobalClipboard)) if (!FireClipboardEvent(ePaste, nsIClipboard::kGlobalClipboard)) {
return NS_OK; return NS_OK;
}
// handle transferable hooks // handle transferable hooks
nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument(); nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
@ -1424,8 +1426,9 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
// //
NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(int32_t aSelectionType) NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(int32_t aSelectionType)
{ {
if (!FireClipboardEvent(NS_PASTE, aSelectionType)) if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK; return NS_OK;
}
ForceCompositionEnd(); ForceCompositionEnd();

View File

@ -322,8 +322,9 @@ nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
NS_IMETHODIMP nsPlaintextEditor::Paste(int32_t aSelectionType) NS_IMETHODIMP nsPlaintextEditor::Paste(int32_t aSelectionType)
{ {
if (!FireClipboardEvent(NS_PASTE, aSelectionType)) if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK; return NS_OK;
}
// Get Clipboard Service // Get Clipboard Service
nsresult rv; nsresult rv;
@ -355,8 +356,9 @@ NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferabl
{ {
// Use an invalid value for the clipboard type as data comes from aTransferable // Use an invalid value for the clipboard type as data comes from aTransferable
// and we don't currently implement a way to put that in the data transfer yet. // and we don't currently implement a way to put that in the data transfer yet.
if (!FireClipboardEvent(NS_PASTE, -1)) if (!FireClipboardEvent(ePaste, -1)) {
return NS_OK; return NS_OK;
}
if (!IsModifiable()) if (!IsModifiable())
return NS_OK; return NS_OK;

View File

@ -1173,7 +1173,7 @@ nsPlaintextEditor::FireClipboardEvent(EventMessage aEventMessage,
int32_t aSelectionType, int32_t aSelectionType,
bool* aActionTaken) bool* aActionTaken)
{ {
if (aEventMessage == NS_PASTE) { if (aEventMessage == ePaste) {
ForceCompositionEnd(); ForceCompositionEnd();
} }
@ -1198,7 +1198,7 @@ nsPlaintextEditor::FireClipboardEvent(EventMessage aEventMessage,
NS_IMETHODIMP nsPlaintextEditor::Cut() NS_IMETHODIMP nsPlaintextEditor::Cut()
{ {
bool actionTaken = false; bool actionTaken = false;
if (FireClipboardEvent(NS_CUT, nsIClipboard::kGlobalClipboard, &actionTaken)) { if (FireClipboardEvent(eCut, nsIClipboard::kGlobalClipboard, &actionTaken)) {
DeleteSelection(eNone, eStrip); DeleteSelection(eNone, eStrip);
} }
return actionTaken ? NS_OK : NS_ERROR_FAILURE; return actionTaken ? NS_OK : NS_ERROR_FAILURE;
@ -1217,7 +1217,7 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(bool *aCanCut)
NS_IMETHODIMP nsPlaintextEditor::Copy() NS_IMETHODIMP nsPlaintextEditor::Copy()
{ {
bool actionTaken = false; bool actionTaken = false;
FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, &actionTaken); FireClipboardEvent(eCopy, nsIClipboard::kGlobalClipboard, &actionTaken);
return actionTaken ? NS_OK : NS_ERROR_FAILURE; return actionTaken ? NS_OK : NS_ERROR_FAILURE;
} }

View File

@ -629,6 +629,12 @@ FilterNodeSoftware::GetOutput(const IntRect &aRect)
void void
FilterNodeSoftware::RequestRect(const IntRect &aRect) FilterNodeSoftware::RequestRect(const IntRect &aRect)
{ {
if (mRequestedRect.Contains(aRect)) {
// Bail out now. Otherwise pathological filters can spend time exponential
// in the number of primitives, e.g. if each primitive takes the
// previous primitive as its two inputs.
return;
}
mRequestedRect = mRequestedRect.Union(aRect); mRequestedRect = mRequestedRect.Union(aRect);
RequestFromInputsForRect(aRect); RequestFromInputsForRect(aRect);
} }

View File

@ -5,7 +5,6 @@
#ifndef gfx_src_DriverCrashGuard_h__ #ifndef gfx_src_DriverCrashGuard_h__
#define gfx_src_DriverCrashGuard_h__ #define gfx_src_DriverCrashGuard_h__
#include "gfxCore.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIGfxInfo.h" #include "nsIGfxInfo.h"
#include "nsIFile.h" #include "nsIFile.h"

View File

@ -347,6 +347,12 @@ FilterCachedColorModels::WrapForColorModel(ColorModel aColorModel)
return FilterWrappers::LinearRGBToSRGB(mDT, unpremultipliedOriginal); return FilterWrappers::LinearRGBToSRGB(mDT, unpremultipliedOriginal);
} }
static const float identityMatrix[] =
{ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0 };
// When aAmount == 0, the identity matrix is returned. // When aAmount == 0, the identity matrix is returned.
// When aAmount == 1, aToMatrix is returned. // When aAmount == 1, aToMatrix is returned.
// When aAmount > 1, an exaggerated version of aToMatrix is returned. This can // When aAmount > 1, an exaggerated version of aToMatrix is returned. This can
@ -363,12 +369,6 @@ static void
InterpolateFromIdentityMatrix(const float aToMatrix[20], float aAmount, InterpolateFromIdentityMatrix(const float aToMatrix[20], float aAmount,
float aOutMatrix[20]) float aOutMatrix[20])
{ {
static const float identityMatrix[] =
{ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0 };
PodCopy(aOutMatrix, identityMatrix, 20); PodCopy(aOutMatrix, identityMatrix, 20);
float oneMinusAmount = 1 - aAmount; float oneMinusAmount = 1 - aAmount;
@ -392,12 +392,6 @@ static nsresult
ComputeColorMatrix(uint32_t aColorMatrixType, const nsTArray<float>& aValues, ComputeColorMatrix(uint32_t aColorMatrixType, const nsTArray<float>& aValues,
float aOutMatrix[20]) float aOutMatrix[20])
{ {
static const float identityMatrix[] =
{ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0 };
// Luminance coefficients. // Luminance coefficients.
static const float lumR = 0.2126f; static const float lumR = 0.2126f;
static const float lumG = 0.7152f; static const float lumG = 0.7152f;
@ -760,7 +754,8 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
float colorMatrix[20]; float colorMatrix[20];
uint32_t type = atts.GetUint(eColorMatrixType); uint32_t type = atts.GetUint(eColorMatrixType);
const nsTArray<float>& values = atts.GetFloats(eColorMatrixValues); const nsTArray<float>& values = atts.GetFloats(eColorMatrixValues);
if (NS_FAILED(ComputeColorMatrix(type, values, colorMatrix))) { if (NS_FAILED(ComputeColorMatrix(type, values, colorMatrix)) ||
PodEqual(colorMatrix, identityMatrix)) {
RefPtr<FilterNode> filter(aSources[0]); RefPtr<FilterNode> filter(aSources[0]);
return filter.forget(); return filter.forget();
} }
@ -954,11 +949,15 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
RefPtr<FilterNode> filter; RefPtr<FilterNode> filter;
uint32_t op = atts.GetUint(eCompositeOperator); uint32_t op = atts.GetUint(eCompositeOperator);
if (op == SVG_FECOMPOSITE_OPERATOR_ARITHMETIC) { if (op == SVG_FECOMPOSITE_OPERATOR_ARITHMETIC) {
const nsTArray<float>& coefficients = atts.GetFloats(eCompositeCoefficients);
static const float allZero[4] = { 0, 0, 0, 0 };
filter = aDT->CreateFilter(FilterType::ARITHMETIC_COMBINE); filter = aDT->CreateFilter(FilterType::ARITHMETIC_COMBINE);
if (!filter) { // All-zero coefficients sometimes occur in junk filters.
if (!filter ||
(coefficients.Length() == ArrayLength(allZero) &&
PodEqual(coefficients.Elements(), allZero, ArrayLength(allZero)))) {
return nullptr; return nullptr;
} }
const nsTArray<float>& coefficients = atts.GetFloats(eCompositeCoefficients);
filter->SetAttribute(ATT_ARITHMETIC_COMBINE_COEFFICIENTS, filter->SetAttribute(ATT_ARITHMETIC_COMBINE_COEFFICIENTS,
coefficients.Elements(), coefficients.Length()); coefficients.Elements(), coefficients.Length());
filter->SetInput(IN_ARITHMETIC_COMBINE_IN, aSources[0]); filter->SetInput(IN_ARITHMETIC_COMBINE_IN, aSources[0]);

View File

@ -22,7 +22,6 @@
#endif #endif
#include <string.h> // for memset #include <string.h> // for memset
#include "gfxCore.h" // for NS_GFX
#include "mozilla/Scoped.h" // for SCOPED_TEMPLATE #include "mozilla/Scoped.h" // for SCOPED_TEMPLATE
namespace mozilla { namespace mozilla {
@ -91,7 +90,7 @@ SCOPED_TEMPLATE(ScopedXFree, ScopedXFreePtrTraits)
* This class is not thread-safe at all. It is assumed that only one thread is using any ScopedXErrorHandler's. Given that it's * This class is not thread-safe at all. It is assumed that only one thread is using any ScopedXErrorHandler's. Given that it's
* not used on Mac, it should be easy to make it thread-safe by using thread-local storage with __thread. * not used on Mac, it should be easy to make it thread-safe by using thread-local storage with __thread.
*/ */
class NS_GFX ScopedXErrorHandler class ScopedXErrorHandler
{ {
public: public:
// trivial wrapper around XErrorEvent, just adding ctor initializing by zero. // trivial wrapper around XErrorEvent, just adding ctor initializing by zero.

View File

@ -1,15 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef gfxCore_h__
#define gfxCore_h__
#include "nscore.h"
#define NS_GFX
#define NS_GFX_(type) type
#define NS_GFX_STATIC_MEMBER_(type) type
#endif

View File

@ -6,7 +6,6 @@
#ifndef gfxCrashReporterUtils_h__ #ifndef gfxCrashReporterUtils_h__
#define gfxCrashReporterUtils_h__ #define gfxCrashReporterUtils_h__
#include "gfxCore.h"
namespace mozilla { namespace mozilla {
@ -21,7 +20,7 @@ namespace mozilla {
* have many exit points. We don't want to encourage having function with many exit points. * have many exit points. We don't want to encourage having function with many exit points.
* It just happens that our graphics features initialization functions are like that. * It just happens that our graphics features initialization functions are like that.
*/ */
class NS_GFX ScopedGfxFeatureReporter class ScopedGfxFeatureReporter
{ {
public: public:
explicit ScopedGfxFeatureReporter(const char *aFeature, bool force = false) explicit ScopedGfxFeatureReporter(const char *aFeature, bool force = false)

View File

@ -16,7 +16,6 @@ DEFINES['MOZ_APP_VERSION'] = '"%s"' % CONFIG['MOZ_APP_VERSION']
EXPORTS += [ EXPORTS += [
'DriverCrashGuard.h', 'DriverCrashGuard.h',
'FilterSupport.h', 'FilterSupport.h',
'gfxCore.h',
'gfxCrashReporterUtils.h', 'gfxCrashReporterUtils.h',
'gfxTelemetry.h', 'gfxTelemetry.h',
'nsBoundingMetrics.h', 'nsBoundingMetrics.h',

View File

@ -75,8 +75,7 @@ static int ComponentValue(const char16_t* aColorSpec, int aLen, int color, int d
return component; return component;
} }
NS_GFX_(bool) NS_HexToRGB(const nsAString& aColorSpec, bool NS_HexToRGB(const nsAString& aColorSpec, nscolor* aResult)
nscolor* aResult)
{ {
const char16_t* buffer = aColorSpec.BeginReading(); const char16_t* buffer = aColorSpec.BeginReading();
@ -121,7 +120,7 @@ NS_GFX_(bool) NS_HexToRGB(const nsAString& aColorSpec,
// This implements part of the algorithm for legacy behavior described in // This implements part of the algorithm for legacy behavior described in
// http://www.whatwg.org/specs/web-apps/current-work/complete/common-microsyntaxes.html#rules-for-parsing-a-legacy-color-value // http://www.whatwg.org/specs/web-apps/current-work/complete/common-microsyntaxes.html#rules-for-parsing-a-legacy-color-value
NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult) bool NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
{ {
if (aColorSpec.EqualsLiteral("transparent")) { if (aColorSpec.EqualsLiteral("transparent")) {
return false; return false;
@ -185,7 +184,7 @@ NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
return true; return true;
} }
NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult) bool NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
{ {
if (!gColorTable) return false; if (!gColorTable) return false;
@ -203,7 +202,7 @@ NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
// Returns kColorNames, an array of all possible color names, and sets // Returns kColorNames, an array of all possible color names, and sets
// *aSizeArray to the size of that array. Do NOT call free() on this array. // *aSizeArray to the size of that array. Do NOT call free() on this array.
NS_GFX_(const char * const *) NS_AllColorNames(size_t *aSizeArray) const char * const * NS_AllColorNames(size_t *aSizeArray)
{ {
*aSizeArray = ArrayLength(kColorNames); *aSizeArray = ArrayLength(kColorNames);
return kColorNames; return kColorNames;
@ -215,7 +214,7 @@ NS_GFX_(const char * const *) NS_AllColorNames(size_t *aSizeArray)
#define MOZ_BLEND(target, bg, fg, fgalpha) \ #define MOZ_BLEND(target, bg, fg, fgalpha) \
FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha)) FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
NS_GFX_(nscolor) nscolor
NS_ComposeColors(nscolor aBG, nscolor aFG) NS_ComposeColors(nscolor aBG, nscolor aFG)
{ {
// This function uses colors that are non premultiplied alpha. // This function uses colors that are non premultiplied alpha.
@ -264,7 +263,7 @@ HSL_HueToRGB(float m1, float m2, float h)
} }
// The float parameters are all expected to be in the range 0-1 // The float parameters are all expected to be in the range 0-1
NS_GFX_(nscolor) nscolor
NS_HSL2RGB(float h, float s, float l) NS_HSL2RGB(float h, float s, float l)
{ {
uint8_t r, g, b; uint8_t r, g, b;
@ -281,7 +280,7 @@ NS_HSL2RGB(float h, float s, float l)
return NS_RGB(r, g, b); return NS_RGB(r, g, b);
} }
NS_GFX_(const char*) const char*
NS_RGBToColorName(nscolor aColor) NS_RGBToColorName(nscolor aColor)
{ {
for (size_t idx = 0; idx < ArrayLength(kColors); ++idx) { for (size_t idx = 0; idx < ArrayLength(kColors); ++idx) {

View File

@ -8,7 +8,6 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t, uint32_t #include <stdint.h> // for uint8_t, uint32_t
#include "gfxCore.h" // for NS_GFX_
#include "nscore.h" // for nsAString #include "nscore.h" // for nsAString
class nsAString; class nsAString;
@ -53,37 +52,37 @@ typedef uint32_t nscolor;
// Translate a hex string to a color. Return true if it parses ok, // Translate a hex string to a color. Return true if it parses ok,
// otherwise return false. // otherwise return false.
// This accepts only 3 or 6 digits // This accepts only 3 or 6 digits
NS_GFX_(bool) NS_HexToRGB(const nsAString& aBuf, nscolor* aResult); bool NS_HexToRGB(const nsAString& aBuf, nscolor* aResult);
// Compose one NS_RGB color onto another. The result is what // Compose one NS_RGB color onto another. The result is what
// you get if you draw aFG on top of aBG with operator OVER. // you get if you draw aFG on top of aBG with operator OVER.
NS_GFX_(nscolor) NS_ComposeColors(nscolor aBG, nscolor aFG); nscolor NS_ComposeColors(nscolor aBG, nscolor aFG);
// Translate a hex string to a color. Return true if it parses ok, // Translate a hex string to a color. Return true if it parses ok,
// otherwise return false. // otherwise return false.
// This version accepts 1 to 9 digits (missing digits are 0) // This version accepts 1 to 9 digits (missing digits are 0)
NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aBuf, nscolor* aResult); bool NS_LooseHexToRGB(const nsString& aBuf, nscolor* aResult);
// There is no function to translate a color to a hex string, because // There is no function to translate a color to a hex string, because
// the hex-string syntax does not support transparency. // the hex-string syntax does not support transparency.
// Translate a color name to a color. Return true if it parses ok, // Translate a color name to a color. Return true if it parses ok,
// otherwise return false. // otherwise return false.
NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aBuf, nscolor* aResult); bool NS_ColorNameToRGB(const nsAString& aBuf, nscolor* aResult);
// Returns an array of all possible color names, and sets // Returns an array of all possible color names, and sets
// *aSizeArray to the size of that array. Do NOT call |free()| on this array. // *aSizeArray to the size of that array. Do NOT call |free()| on this array.
NS_GFX_(const char * const *) NS_AllColorNames(size_t *aSizeArray); const char * const * NS_AllColorNames(size_t *aSizeArray);
// function to convert from HSL color space to RGB color space // function to convert from HSL color space to RGB color space
// the float parameters are all expected to be in the range 0-1 // the float parameters are all expected to be in the range 0-1
NS_GFX_(nscolor) NS_HSL2RGB(float h, float s, float l); nscolor NS_HSL2RGB(float h, float s, float l);
// Return a color name for the given nscolor. If there is no color // Return a color name for the given nscolor. If there is no color
// name for it, returns null. If there are multiple possible color // name for it, returns null. If there are multiple possible color
// names for the given color, the first one in nsColorNameList.h // names for the given color, the first one in nsColorNameList.h
// (which is generally the first one in alphabetical order) will be // (which is generally the first one in alphabetical order) will be
// returned. // returned.
NS_GFX_(const char*) NS_RGBToColorName(nscolor aColor); const char* NS_RGBToColorName(nscolor aColor);
#endif /* nsColor_h___ */ #endif /* nsColor_h___ */

View File

@ -6,9 +6,8 @@
#ifndef nsColorNames_h___ #ifndef nsColorNames_h___
#define nsColorNames_h___ #define nsColorNames_h___
#include "gfxCore.h"
class NS_GFX nsColorNames { class nsColorNames {
public: public:
static void AddRefTable(void); static void AddRefTable(void);
static void ReleaseTable(void); static void ReleaseTable(void);

View File

@ -8,7 +8,6 @@
#include <stdint.h> // for uint8_t, uint16_t #include <stdint.h> // for uint8_t, uint16_t
#include <sys/types.h> // for int16_t #include <sys/types.h> // for int16_t
#include "gfxCore.h" // for NS_GFX
#include "gfxFontFamilyList.h" #include "gfxFontFamilyList.h"
#include "gfxFontFeatures.h" #include "gfxFontFeatures.h"
#include "nsAutoPtr.h" // for nsRefPtr #include "nsAutoPtr.h" // for nsRefPtr
@ -40,7 +39,7 @@ const uint8_t kGenericFont_cursive = 0x10;
const uint8_t kGenericFont_fantasy = 0x20; const uint8_t kGenericFont_fantasy = 0x20;
// Font structure. // Font structure.
struct NS_GFX nsFont { struct nsFont {
// list of font families, either named or generic // list of font families, either named or generic
mozilla::FontFamilyList fontlist; mozilla::FontFamilyList fontlist;

View File

@ -8,7 +8,6 @@
#include "nsCoord.h" #include "nsCoord.h"
#include "nsPoint.h" #include "nsPoint.h"
#include "gfxCore.h"
#include "mozilla/gfx/BaseMargin.h" #include "mozilla/gfx/BaseMargin.h"
struct nsMargin : public mozilla::gfx::BaseMargin<nscoord, nsMargin> { struct nsMargin : public mozilla::gfx::BaseMargin<nscoord, nsMargin> {

View File

@ -10,7 +10,6 @@
#include <stdio.h> // for FILE #include <stdio.h> // for FILE
#include <stdint.h> // for int32_t, int64_t #include <stdint.h> // for int32_t, int64_t
#include <algorithm> // for min/max #include <algorithm> // for min/max
#include "gfxCore.h" // for NS_GFX
#include "mozilla/Likely.h" // for MOZ_UNLIKELY #include "mozilla/Likely.h" // for MOZ_UNLIKELY
#include "mozilla/gfx/Rect.h" #include "mozilla/gfx/Rect.h"
#include "nsCoord.h" // for nscoord, etc #include "nsCoord.h" // for nscoord, etc
@ -24,7 +23,7 @@ struct nsIntMargin;
typedef mozilla::gfx::IntRect nsIntRect; typedef mozilla::gfx::IntRect nsIntRect;
struct NS_GFX nsRect : struct nsRect :
public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> { public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> {
typedef mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> Super; typedef mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> Super;
@ -290,7 +289,7 @@ ToAppUnits(const mozilla::gfx::IntRect& aRect, nscoord aAppUnitsPerPixel);
#ifdef DEBUG #ifdef DEBUG
// Diagnostics // Diagnostics
extern NS_GFX FILE* operator<<(FILE* out, const nsRect& rect); extern FILE* operator<<(FILE* out, const nsRect& rect);
#endif // DEBUG #endif // DEBUG
#endif /* NSRECT_H */ #endif /* NSRECT_H */

View File

@ -9,7 +9,6 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint64_t #include <stdint.h> // for uint32_t, uint64_t
#include <sys/types.h> // for int32_t #include <sys/types.h> // for int32_t
#include "gfxCore.h" // for NS_GFX
#include "mozilla/ToString.h" // for mozilla::ToString #include "mozilla/ToString.h" // for mozilla::ToString
#include "nsCoord.h" // for nscoord #include "nsCoord.h" // for nscoord
#include "nsError.h" // for nsresult #include "nsError.h" // for nsresult
@ -420,7 +419,7 @@ private:
}; };
class NS_GFX nsRegionRectIterator class nsRegionRectIterator
{ {
const nsRegion* mRegion; const nsRegion* mRegion;
int i; int i;
@ -474,7 +473,7 @@ namespace gfx {
* BaseIntRegions use int32_t coordinates. * BaseIntRegions use int32_t coordinates.
*/ */
template <typename Derived, typename Rect, typename Point, typename Margin> template <typename Derived, typename Rect, typename Point, typename Margin>
class NS_GFX BaseIntRegion class BaseIntRegion
{ {
friend class ::nsRegion; friend class ::nsRegion;
@ -763,7 +762,7 @@ public:
nsCString ToString() const { return mImpl.ToString(); } nsCString ToString() const { return mImpl.ToString(); }
class NS_GFX RectIterator class RectIterator
{ {
nsRegionRectIterator mImpl; nsRegionRectIterator mImpl;
Rect mTmp; Rect mTmp;
@ -825,7 +824,7 @@ private:
} // namespace gfx } // namespace gfx
} // namespace mozilla } // namespace mozilla
class NS_GFX nsIntRegion : public mozilla::gfx::BaseIntRegion<nsIntRegion, mozilla::gfx::IntRect, nsIntPoint, nsIntMargin> class nsIntRegion : public mozilla::gfx::BaseIntRegion<nsIntRegion, mozilla::gfx::IntRect, nsIntPoint, nsIntMargin>
{ {
public: public:
// Forward constructors. // Forward constructors.

View File

@ -8,12 +8,11 @@
#define nsScriptableRegion_h #define nsScriptableRegion_h
#include "nsIScriptableRegion.h" #include "nsIScriptableRegion.h"
#include "gfxCore.h"
#include "nsISupports.h" #include "nsISupports.h"
#include "nsRegion.h" #include "nsRegion.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
class NS_GFX nsScriptableRegion final : public nsIScriptableRegion { class nsScriptableRegion final : public nsIScriptableRegion {
public: public:
nsScriptableRegion(); nsScriptableRegion();

View File

@ -6,10 +6,9 @@
#ifndef nsTransform2D_h___ #ifndef nsTransform2D_h___
#define nsTransform2D_h___ #define nsTransform2D_h___
#include "gfxCore.h"
#include "nsCoord.h" #include "nsCoord.h"
class NS_GFX nsTransform2D class nsTransform2D
{ {
private: private:
/** /**

View File

@ -1,7 +1,7 @@
diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
--- a/gfx/ycbcr/yuv_convert.cpp --- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp +++ b/gfx/ycbcr/yuv_convert.cpp
@@ -337,16 +337,17 @@ NS_GFX_(void) ScaleYCbCrToRGB32(const ui @@ -337,16 +337,17 @@ void ScaleYCbCrToRGB32(const uint* yplan
source_dx_uv >> kFractionBits); source_dx_uv >> kFractionBits);
} }
} }

View File

@ -10,10 +10,10 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
const int kFractionMax = 1 << kFractionBits; const int kFractionMax = 1 << kFractionBits;
const int kFractionMask = ((1 << kFractionBits) - 1); const int kFractionMask = ((1 << kFractionBits) - 1);
+NS_GFX_(YUVType) TypeFromSize(int ywidth, +YUVType TypeFromSize(int ywidth,
+ int yheight, + int yheight,
+ int cbcrwidth, + int cbcrwidth,
+ int cbcrheight) + int cbcrheight)
+{ +{
+ if (ywidth == cbcrwidth && yheight == cbcrheight) { + if (ywidth == cbcrwidth && yheight == cbcrheight) {
+ return YV24; + return YV24;
@ -27,13 +27,13 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
+} +}
+ +
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf, void ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf, const uint8* u_buf,
const uint8* v_buf, const uint8* v_buf,
uint8* rgb_buf, uint8* rgb_buf,
int pic_x, int pic_x,
int pic_y, int pic_y,
int pic_width, int pic_width,
diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
--- a/gfx/ycbcr/yuv_convert.h --- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h +++ b/gfx/ycbcr/yuv_convert.h
@ -46,13 +46,13 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
FILTER_BILINEAR = 3 // Bilinear filter. FILTER_BILINEAR = 3 // Bilinear filter.
}; };
+NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight); +YUVType TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
+ +
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
// Pass in YV16/YV12 depending on source format // Pass in YV16/YV12 depending on source format
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane, void ConvertYCbCrToRGB32(const uint8* yplane,
const uint8* uplane, const uint8* uplane,
const uint8* vplane, const uint8* vplane,
uint8* rgbframe, uint8* rgbframe,
int pic_x, int pic_x,
int pic_y, int pic_y,

View File

@ -71,18 +71,18 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
- rgb_row, - rgb_row,
- width); - width);
- } - }
+NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf, +void ConvertYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf, + const uint8* u_buf,
+ const uint8* v_buf, + const uint8* v_buf,
+ uint8* rgb_buf, + uint8* rgb_buf,
+ int pic_x, + int pic_x,
+ int pic_y, + int pic_y,
+ int pic_width, + int pic_width,
+ int pic_height, + int pic_height,
+ int y_pitch, + int y_pitch,
+ int uv_pitch, + int uv_pitch,
+ int rgb_pitch, + int rgb_pitch,
+ YUVType yuv_type) { + YUVType yuv_type) {
+ unsigned int y_shift = yuv_type == YV12 ? 1 : 0; + unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
+ unsigned int x_shift = yuv_type == YV24 ? 0 : 1; + unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
+ // Test for SSE because the optimized code uses movntq, which is not part of MMX. + // Test for SSE because the optimized code uses movntq, which is not part of MMX.
@ -275,20 +275,20 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
- YUVType yuv_type, - YUVType yuv_type,
- Rotate view_rotate, - Rotate view_rotate,
- ScaleFilter filter) { - ScaleFilter filter) {
+NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* y_buf, +void ScaleYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf, + const uint8* u_buf,
+ const uint8* v_buf, + const uint8* v_buf,
+ uint8* rgb_buf, + uint8* rgb_buf,
+ int source_width, + int source_width,
+ int source_height, + int source_height,
+ int width, + int width,
+ int height, + int height,
+ int y_pitch, + int y_pitch,
+ int uv_pitch, + int uv_pitch,
+ int rgb_pitch, + int rgb_pitch,
+ YUVType yuv_type, + YUVType yuv_type,
+ Rotate view_rotate, + Rotate view_rotate,
+ ScaleFilter filter) { + ScaleFilter filter) {
+ bool has_mmx = supports_mmx(); + bool has_mmx = supports_mmx();
+ +
// 4096 allows 3 buffers to fit in 12k. // 4096 allows 3 buffers to fit in 12k.
@ -469,18 +469,18 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
- int uvstride, - int uvstride,
- int rgbstride, - int rgbstride,
- YUVType yuv_type); - YUVType yuv_type);
+NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane, +void ConvertYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane, + const uint8* uplane,
+ const uint8* vplane, + const uint8* vplane,
+ uint8* rgbframe, + uint8* rgbframe,
+ int pic_x, + int pic_x,
+ int pic_y, + int pic_y,
+ int pic_width, + int pic_width,
+ int pic_height, + int pic_height,
+ int ystride, + int ystride,
+ int uvstride, + int uvstride,
+ int rgbstride, + int rgbstride,
+ YUVType yuv_type); + YUVType yuv_type);
// Scale a frame of YUV to 32 bit ARGB. // Scale a frame of YUV to 32 bit ARGB.
// Supports rotation and mirroring. // Supports rotation and mirroring.
@ -501,20 +501,20 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
- -
-} // namespace media -} // namespace media
- -
+NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* yplane, +void ScaleYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane, + const uint8* uplane,
+ const uint8* vplane, + const uint8* vplane,
+ uint8* rgbframe, + uint8* rgbframe,
+ int source_width, + int source_width,
+ int source_height, + int source_height,
+ int width, + int width,
+ int height, + int height,
+ int ystride, + int ystride,
+ int uvstride, + int uvstride,
+ int rgbstride, + int rgbstride,
+ YUVType yuv_type, + YUVType yuv_type,
+ Rotate view_rotate, + Rotate view_rotate,
+ ScaleFilter filter); + ScaleFilter filter);
+ +
+} // namespace gfx +} // namespace gfx
+} // namespace mozilla +} // namespace mozilla

View File

@ -281,7 +281,7 @@ static void ScaleYCbCr444ToRGB565_Nearest_Row_C(
} }
} }
NS_GFX_(void) ScaleYCbCrToRGB565(const uint8_t *y_buf, void ScaleYCbCrToRGB565(const uint8_t *y_buf,
const uint8_t *u_buf, const uint8_t *u_buf,
const uint8_t *v_buf, const uint8_t *v_buf,
uint8_t *rgb_buf, uint8_t *rgb_buf,
@ -537,7 +537,7 @@ NS_GFX_(void) ScaleYCbCrToRGB565(const uint8_t *y_buf,
} }
} }
NS_GFX_(bool) IsScaleYCbCrToRGB565Fast(int source_x0, bool IsScaleYCbCrToRGB565Fast(int source_x0,
int source_y0, int source_y0,
int source_width, int source_width,
int source_height, int source_height,
@ -599,7 +599,7 @@ void yuv_to_rgb565_row_c(uint16 *dst,
} }
} }
NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* y_buf, void ConvertYCbCrToRGB565(const uint8* y_buf,
const uint8* u_buf, const uint8* u_buf,
const uint8* v_buf, const uint8* v_buf,
uint8* rgb_buf, uint8* rgb_buf,
@ -652,7 +652,7 @@ NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* y_buf,
} }
} }
NS_GFX_(bool) IsConvertYCbCrToRGB565Fast(int pic_x, bool IsConvertYCbCrToRGB565Fast(int pic_x,
int pic_y, int pic_y,
int pic_width, int pic_width,
int pic_height, int pic_height,

View File

@ -17,7 +17,7 @@ namespace gfx {
#ifdef HAVE_YCBCR_TO_RGB565 #ifdef HAVE_YCBCR_TO_RGB565
// Convert a frame of YUV to 16 bit RGB565. // Convert a frame of YUV to 16 bit RGB565.
NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane, void ConvertYCbCrToRGB565(const uint8* yplane,
const uint8* uplane, const uint8* uplane,
const uint8* vplane, const uint8* vplane,
uint8* rgbframe, uint8* rgbframe,
@ -31,14 +31,14 @@ NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane,
YUVType yuv_type); YUVType yuv_type);
// Used to test if we have an accelerated version. // Used to test if we have an accelerated version.
NS_GFX_(bool) IsConvertYCbCrToRGB565Fast(int pic_x, bool IsConvertYCbCrToRGB565Fast(int pic_x,
int pic_y, int pic_y,
int pic_width, int pic_width,
int pic_height, int pic_height,
YUVType yuv_type); YUVType yuv_type);
// Scale a frame of YUV to 16 bit RGB565. // Scale a frame of YUV to 16 bit RGB565.
NS_GFX_(void) ScaleYCbCrToRGB565(const uint8_t *yplane, void ScaleYCbCrToRGB565(const uint8_t *yplane,
const uint8_t *uplane, const uint8_t *uplane,
const uint8_t *vplane, const uint8_t *vplane,
uint8_t *rgbframe, uint8_t *rgbframe,
@ -55,7 +55,7 @@ NS_GFX_(void) ScaleYCbCrToRGB565(const uint8_t *yplane,
ScaleFilter filter); ScaleFilter filter);
// Used to test if we have an accelerated version. // Used to test if we have an accelerated version.
NS_GFX_(bool) IsScaleYCbCrToRGB565Fast(int source_x0, bool IsScaleYCbCrToRGB565Fast(int source_x0,
int source_y0, int source_y0,
int source_width, int source_width,
int source_height, int source_height,

View File

@ -31,7 +31,7 @@ const int kFractionBits = 16;
const int kFractionMax = 1 << kFractionBits; const int kFractionMax = 1 << kFractionBits;
const int kFractionMask = ((1 << kFractionBits) - 1); const int kFractionMask = ((1 << kFractionBits) - 1);
NS_GFX_(YUVType) TypeFromSize(int ywidth, YUVType TypeFromSize(int ywidth,
int yheight, int yheight,
int cbcrwidth, int cbcrwidth,
int cbcrheight) int cbcrheight)
@ -48,18 +48,18 @@ NS_GFX_(YUVType) TypeFromSize(int ywidth,
} }
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf, void ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf, const uint8* u_buf,
const uint8* v_buf, const uint8* v_buf,
uint8* rgb_buf, uint8* rgb_buf,
int pic_x, int pic_x,
int pic_y, int pic_y,
int pic_width, int pic_width,
int pic_height, int pic_height,
int y_pitch, int y_pitch,
int uv_pitch, int uv_pitch,
int rgb_pitch, int rgb_pitch,
YUVType yuv_type) { YUVType yuv_type) {
unsigned int y_shift = yuv_type == YV12 ? 1 : 0; unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
unsigned int x_shift = yuv_type == YV24 ? 0 : 1; unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
// Test for SSE because the optimized code uses movntq, which is not part of MMX. // Test for SSE because the optimized code uses movntq, which is not part of MMX.
@ -163,20 +163,20 @@ static inline void FilterRows(uint8* ybuf, const uint8* y0_ptr,
// Scale a frame of YUV to 32 bit ARGB. // Scale a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* y_buf, void ScaleYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf, const uint8* u_buf,
const uint8* v_buf, const uint8* v_buf,
uint8* rgb_buf, uint8* rgb_buf,
int source_width, int source_width,
int source_height, int source_height,
int width, int width,
int height, int height,
int y_pitch, int y_pitch,
int uv_pitch, int uv_pitch,
int rgb_pitch, int rgb_pitch,
YUVType yuv_type, YUVType yuv_type,
Rotate view_rotate, Rotate view_rotate,
ScaleFilter filter) { ScaleFilter filter) {
bool has_mmx = supports_mmx(); bool has_mmx = supports_mmx();
// 4096 allows 3 buffers to fit in 12k. // 4096 allows 3 buffers to fit in 12k.

View File

@ -6,7 +6,6 @@
#define MEDIA_BASE_YUV_CONVERT_H_ #define MEDIA_BASE_YUV_CONVERT_H_
#include "chromium_types.h" #include "chromium_types.h"
#include "gfxCore.h"
namespace mozilla { namespace mozilla {
@ -41,39 +40,39 @@ enum ScaleFilter {
FILTER_BILINEAR = 3 // Bilinear filter. FILTER_BILINEAR = 3 // Bilinear filter.
}; };
NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight); YUVType TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
// Pass in YV16/YV12 depending on source format // Pass in YV16/YV12 depending on source format
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane, void ConvertYCbCrToRGB32(const uint8* yplane,
const uint8* uplane, const uint8* uplane,
const uint8* vplane, const uint8* vplane,
uint8* rgbframe, uint8* rgbframe,
int pic_x, int pic_x,
int pic_y, int pic_y,
int pic_width, int pic_width,
int pic_height, int pic_height,
int ystride, int ystride,
int uvstride, int uvstride,
int rgbstride, int rgbstride,
YUVType yuv_type); YUVType yuv_type);
// Scale a frame of YUV to 32 bit ARGB. // Scale a frame of YUV to 32 bit ARGB.
// Supports rotation and mirroring. // Supports rotation and mirroring.
NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* yplane, void ScaleYCbCrToRGB32(const uint8* yplane,
const uint8* uplane, const uint8* uplane,
const uint8* vplane, const uint8* vplane,
uint8* rgbframe, uint8* rgbframe,
int source_width, int source_width,
int source_height, int source_height,
int width, int width,
int height, int height,
int ystride, int ystride,
int uvstride, int uvstride,
int rgbstride, int rgbstride,
YUVType yuv_type, YUVType yuv_type,
Rotate view_rotate, Rotate view_rotate,
ScaleFilter filter); ScaleFilter filter);
} // namespace gfx } // namespace gfx
} // namespace mozilla } // namespace mozilla

View File

@ -418,9 +418,10 @@ Decoder::PostIsAnimated(int32_t aFirstFrameTimeout)
} }
void void
Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */, Decoder::PostFrameStop(Opacity aFrameOpacity
/* = Opacity::SOME_TRANSPARENCY */,
DisposalMethod aDisposalMethod DisposalMethod aDisposalMethod
/* = DisposalMethod::KEEP */, /* = DisposalMethod::KEEP */,
int32_t aTimeout /* = 0 */, int32_t aTimeout /* = 0 */,
BlendMethod aBlendMethod /* = BlendMethod::OVER */) BlendMethod aBlendMethod /* = BlendMethod::OVER */)
{ {

View File

@ -27,6 +27,7 @@ Downscaler::Downscaler(const nsIntSize& aTargetSize)
, mYFilter(MakeUnique<skia::ConvolutionFilter1D>()) , mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
, mWindowCapacity(0) , mWindowCapacity(0)
, mHasAlpha(true) , mHasAlpha(true)
, mFlipVertically(false)
{ {
MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(), MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(),
"Downscaling even though downscale-during-decode is disabled?"); "Downscaling even though downscale-during-decode is disabled?");
@ -57,7 +58,8 @@ Downscaler::ReleaseWindow()
nsresult nsresult
Downscaler::BeginFrame(const nsIntSize& aOriginalSize, Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
uint8_t* aOutputBuffer, uint8_t* aOutputBuffer,
bool aHasAlpha) bool aHasAlpha,
bool aFlipVertically /* = false */)
{ {
MOZ_ASSERT(aOutputBuffer); MOZ_ASSERT(aOutputBuffer);
MOZ_ASSERT(mTargetSize != aOriginalSize, MOZ_ASSERT(mTargetSize != aOriginalSize,
@ -74,6 +76,7 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
double(mOriginalSize.height) / mTargetSize.height); double(mOriginalSize.height) / mTargetSize.height);
mOutputBuffer = aOutputBuffer; mOutputBuffer = aOutputBuffer;
mHasAlpha = aHasAlpha; mHasAlpha = aHasAlpha;
mFlipVertically = aFlipVertically;
ResetForNextProgressivePass(); ResetForNextProgressivePass();
ReleaseWindow(); ReleaseWindow();
@ -145,6 +148,16 @@ GetFilterOffsetAndLength(UniquePtr<skia::ConvolutionFilter1D>& aFilter,
aFilterLengthOut); aFilterLengthOut);
} }
void
Downscaler::ClearRow(uint32_t aStartingAtCol)
{
MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
* sizeof(uint32_t);
memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
0, bytesToClear);
}
void void
Downscaler::CommitRow() Downscaler::CommitRow()
{ {
@ -198,9 +211,18 @@ Downscaler::TakeInvalidRect()
DownscalerInvalidRect invalidRect; DownscalerInvalidRect invalidRect;
// Compute the target size invalid rect. // Compute the target size invalid rect.
invalidRect.mTargetSizeRect = if (mFlipVertically) {
nsIntRect(0, mPrevInvalidatedLine, // We need to flip it. This will implicitly flip the original size invalid
// rect, since we compute it by scaling this rect.
invalidRect.mTargetSizeRect =
IntRect(0, mTargetSize.height - mCurrentOutLine,
mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine); mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
} else {
invalidRect.mTargetSizeRect =
IntRect(0, mPrevInvalidatedLine,
mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
}
mPrevInvalidatedLine = mCurrentOutLine; mPrevInvalidatedLine = mCurrentOutLine;
// Compute the original size invalid rect. // Compute the original size invalid rect.
@ -225,8 +247,13 @@ Downscaler::DownscaleInputLine()
auto filterValues = auto filterValues =
mYFilter->FilterForValue(mCurrentOutLine, &filterOffset, &filterLength); mYFilter->FilterForValue(mCurrentOutLine, &filterOffset, &filterLength);
int32_t currentOutLine = mFlipVertically
? mTargetSize.height - (mCurrentOutLine + 1)
: mCurrentOutLine;
MOZ_ASSERT(currentOutLine >= 0);
uint8_t* outputLine = uint8_t* outputLine =
&mOutputBuffer[mCurrentOutLine * mTargetSize.width * sizeof(uint32_t)]; &mOutputBuffer[currentOutLine * mTargetSize.width * sizeof(uint32_t)];
skia::ConvolveVertically(static_cast<const FilterValue*>(filterValues), skia::ConvolveVertically(static_cast<const FilterValue*>(filterValues),
filterLength, mWindow.get(), mXFilter->num_values(), filterLength, mWindow.get(), mXFilter->num_values(),
outputLine, mHasAlpha, supports_sse2()); outputLine, mHasAlpha, supports_sse2());

View File

@ -70,14 +70,21 @@ public:
* decode. * decode.
* @param aHasAlpha Whether or not this frame has an alpha channel. * @param aHasAlpha Whether or not this frame has an alpha channel.
* Performance is a little better if it doesn't have one. * Performance is a little better if it doesn't have one.
* @param aFlipVertically If true, output rows will be written to the output
* buffer in reverse order vertically, which matches
* the way they are stored in some image formats.
*/ */
nsresult BeginFrame(const nsIntSize& aOriginalSize, nsresult BeginFrame(const nsIntSize& aOriginalSize,
uint8_t* aOutputBuffer, uint8_t* aOutputBuffer,
bool aHasAlpha); bool aHasAlpha,
bool aFlipVertically = false);
/// Retrieves the buffer into which the Decoder should write each row. /// Retrieves the buffer into which the Decoder should write each row.
uint8_t* RowBuffer() { return mRowBuffer.get(); } uint8_t* RowBuffer() { return mRowBuffer.get(); }
/// Clears the current row buffer (optionally starting at @aStartingAtCol).
void ClearRow(uint32_t aStartingAtCol = 0);
/// Signals that the decoder has finished writing a row into the row buffer. /// Signals that the decoder has finished writing a row into the row buffer.
void CommitRow(); void CommitRow();
@ -117,7 +124,8 @@ private:
int32_t mCurrentOutLine; int32_t mCurrentOutLine;
int32_t mCurrentInLine; int32_t mCurrentInLine;
bool mHasAlpha; bool mHasAlpha : 1;
bool mFlipVertically : 1;
}; };
#else #else
@ -139,12 +147,13 @@ public:
const nsIntSize& TargetSize() const { return nsIntSize(); } const nsIntSize& TargetSize() const { return nsIntSize(); }
const gfxSize& Scale() const { return gfxSize(1.0, 1.0); } const gfxSize& Scale() const { return gfxSize(1.0, 1.0); }
nsresult BeginFrame(const nsIntSize&, uint8_t*, bool) nsresult BeginFrame(const nsIntSize&, uint8_t*, bool, bool = false)
{ {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
uint8_t* RowBuffer() { return nullptr; } uint8_t* RowBuffer() { return nullptr; }
void ClearRow(uint32_t = 0);
void CommitRow() { } void CommitRow() { }
bool HasInvalidation() const { return false; } bool HasInvalidation() const { return false; }
DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); } DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }

View File

@ -36,7 +36,10 @@ static bool
ShouldDownscaleDuringDecode(const nsCString& aMimeType) ShouldDownscaleDuringDecode(const nsCString& aMimeType)
{ {
DecoderType type = DecoderFactory::GetDecoderType(aMimeType.get()); DecoderType type = DecoderFactory::GetDecoderType(aMimeType.get());
return type == DecoderType::JPEG || type == DecoderType::PNG; return type == DecoderType::JPEG ||
type == DecoderType::ICON ||
type == DecoderType::PNG ||
type == DecoderType::BMP;
} }
static uint32_t static uint32_t

View File

@ -19,6 +19,8 @@
#include "RasterImage.h" #include "RasterImage.h"
#include <algorithm> #include <algorithm>
using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace image { namespace image {
@ -62,6 +64,20 @@ nsBMPDecoder::~nsBMPDecoder()
} }
} }
nsresult
nsBMPDecoder::SetTargetSize(const nsIntSize& aSize)
{
// Make sure the size is reasonable.
if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
return NS_ERROR_FAILURE;
}
// Create a downscaler that we'll filter our output through.
mDownscaler.emplace(aSize);
return NS_OK;
}
// Sets whether or not the BMP will use alpha data // Sets whether or not the BMP will use alpha data
void void
nsBMPDecoder::SetUseAlphaData(bool useAlphaData) nsBMPDecoder::SetUseAlphaData(bool useAlphaData)
@ -122,15 +138,6 @@ nsBMPDecoder::GetCompressedImageSize() const
return pixelArraySize; return pixelArraySize;
} }
// Obtains whether or not a BMP file had alpha data in its 4th byte
// for 32BPP bitmaps. Only use after the bitmap has been processed.
bool
nsBMPDecoder::HasAlphaData() const
{
return mHaveAlphaData;
}
void void
nsBMPDecoder::FinishInternal() nsBMPDecoder::FinishInternal()
{ {
@ -147,7 +154,7 @@ nsBMPDecoder::FinishInternal()
nsIntRect r(0, 0, mBIH.width, GetHeight()); nsIntRect r(0, 0, mBIH.width, GetHeight());
PostInvalidation(r); PostInvalidation(r);
if (mUseAlphaData) { if (mUseAlphaData && mHaveAlphaData) {
PostFrameStop(Opacity::SOME_TRANSPARENCY); PostFrameStop(Opacity::SOME_TRANSPARENCY);
} else { } else {
PostFrameStop(Opacity::OPAQUE); PostFrameStop(Opacity::OPAQUE);
@ -372,9 +379,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// We treat BMPs as transparent if they're 32bpp and alpha is enabled, but // We treat BMPs as transparent if they're 32bpp and alpha is enabled, but
// also if they use RLE encoding, because the 'delta' mode can skip pixels // also if they use RLE encoding, because the 'delta' mode can skip pixels
// and cause implicit transparency. // and cause implicit transparency.
if ((mBIH.compression == BMPINFOHEADER::RLE8) || bool hasTransparency = (mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4) || (mBIH.compression == BMPINFOHEADER::RLE4) ||
(mBIH.bpp == 32 && mUseAlphaData)) { (mBIH.bpp == 32 && mUseAlphaData);
if (hasTransparency) {
PostHasTransparency(); PostHasTransparency();
} }
@ -453,18 +461,25 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
} }
MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); MOZ_ASSERT(!mImageData, "Already have a buffer allocated?");
nsresult rv = AllocateBasicFrame(); IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
: GetSize();
nsresult rv = AllocateFrame(/* aFrameNum = */ 0, targetSize,
IntRect(IntPoint(), targetSize),
SurfaceFormat::B8G8R8A8);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;
} }
MOZ_ASSERT(mImageData, "Should have a buffer now"); MOZ_ASSERT(mImageData, "Should have a buffer now");
// Prepare for transparency if (mDownscaler) {
if ((mBIH.compression == BMPINFOHEADER::RLE8) || // BMPs store their rows in reverse order, so the downscaler needs to
(mBIH.compression == BMPINFOHEADER::RLE4)) { // reverse them again when writing its output.
// Clear the image, as the RLE may jump over areas rv = mDownscaler->BeginFrame(GetSize(), mImageData, hasTransparency,
memset(mImageData, 0, mImageDataLength); /* aFlipVertically = */ true);
if (NS_FAILED(rv)) {
return;
}
} }
} }
@ -606,8 +621,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
if (rowSize == mRowBytes) { if (rowSize == mRowBytes) {
// Collected a whole row into mRow, process it // Collected a whole row into mRow, process it
uint8_t* p = mRow; uint8_t* p = mRow;
uint32_t* d = reinterpret_cast<uint32_t*>(mImageData) + uint32_t* d = mDownscaler
PIXEL_OFFSET(mCurLine, 0); ? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, 0);
uint32_t lpos = mBIH.width; uint32_t lpos = mBIH.width;
switch (mBIH.bpp) { switch (mBIH.bpp) {
case 1: case 1:
@ -664,28 +681,11 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case 32: case 32:
while (lpos > 0) { while (lpos > 0) {
if (mUseAlphaData) { if (mUseAlphaData) {
if (!mHaveAlphaData && p[3]) { if (MOZ_UNLIKELY(!mHaveAlphaData && p[3])) {
// Non-zero alpha byte detected! Clear previous
// pixels that we have already processed.
// This works because we know that if we
// are reaching here then the alpha data in byte
// 4 has been right all along. And we know it
// has been set to 0 the whole time, so that
// means that everything is transparent so far.
uint32_t* start = reinterpret_cast<uint32_t*>
(mImageData) + GetWidth() *
(mCurLine - 1);
uint32_t heightDifference = GetHeight() -
mCurLine + 1;
uint32_t pixelCount = GetWidth() *
heightDifference;
memset(start, 0, pixelCount * sizeof(uint32_t));
PostHasTransparency(); PostHasTransparency();
mHaveAlphaData = true; mHaveAlphaData = true;
} }
SetPixel(d, p[2], p[1], p[0], mHaveAlphaData ? p[3] : 0xFF); SetPixel(d, p[2], p[1], p[0], p[3]);
} else { } else {
SetPixel(d, p[2], p[1], p[0]); SetPixel(d, p[2], p[1], p[0]);
} }
@ -697,6 +697,11 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
NS_NOTREACHED("Unsupported color depth," NS_NOTREACHED("Unsupported color depth,"
" but earlier check didn't catch it"); " but earlier check didn't catch it");
} }
if (mDownscaler) {
mDownscaler->CommitRow();
}
mCurLine --; mCurLine --;
if (mCurLine == 0) { // Finished last line if (mCurLine == 0) { // Finished last line
break; break;
@ -741,8 +746,12 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
uint32_t pixelsNeeded = std::min<uint32_t>(mBIH.width - mCurPos, uint32_t pixelsNeeded = std::min<uint32_t>(mBIH.width - mCurPos,
mStateData); mStateData);
if (pixelsNeeded) { if (pixelsNeeded) {
uint32_t* d = reinterpret_cast<uint32_t*> uint32_t* d = mDownscaler
(mImageData) + PIXEL_OFFSET(mCurLine, mCurPos); ? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
+ mCurPos
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, mCurPos);
mCurPos += pixelsNeeded; mCurPos += pixelsNeeded;
if (mBIH.compression == BMPINFOHEADER::RLE8) { if (mBIH.compression == BMPINFOHEADER::RLE8) {
do { do {
@ -761,6 +770,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
switch(byte) { switch(byte) {
case RLE::ESCAPE_EOL: case RLE::ESCAPE_EOL:
// End of Line: Go to next row // End of Line: Go to next row
if (mDownscaler) {
mDownscaler->CommitRow();
}
mCurLine --; mCurLine --;
mCurPos = 0; mCurPos = 0;
mState = eRLEStateInitial; mState = eRLEStateInitial;
@ -810,11 +823,20 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// Handle the XDelta and proceed to get Y Delta // Handle the XDelta and proceed to get Y Delta
byte = *aBuffer++; byte = *aBuffer++;
aCount--; aCount--;
if (mDownscaler) {
// Clear the skipped pixels. (This clears to the end of the row,
// which is perfect if there's a Y delta and harmless if not).
mDownscaler->ClearRow(/* aStartingAtCol = */ mCurPos);
}
mCurPos += byte; mCurPos += byte;
// Delta encoding makes it possible to skip pixels // Delta encoding makes it possible to skip pixels
// making the image transparent. // making the image transparent.
if (MOZ_UNLIKELY(!mHaveAlphaData)) { if (MOZ_UNLIKELY(!mHaveAlphaData)) {
PostHasTransparency(); PostHasTransparency();
mHaveAlphaData = true;
} }
mUseAlphaData = mHaveAlphaData = true; mUseAlphaData = mHaveAlphaData = true;
if (mCurPos > mBIH.width) { if (mCurPos > mBIH.width) {
@ -824,7 +846,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mState = eRLEStateNeedYDelta; mState = eRLEStateNeedYDelta;
continue; continue;
case eRLEStateNeedYDelta: case eRLEStateNeedYDelta: {
// Get the Y Delta and then "handle" the move // Get the Y Delta and then "handle" the move
byte = *aBuffer++; byte = *aBuffer++;
aCount--; aCount--;
@ -833,10 +855,26 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// making the image transparent. // making the image transparent.
if (MOZ_UNLIKELY(!mHaveAlphaData)) { if (MOZ_UNLIKELY(!mHaveAlphaData)) {
PostHasTransparency(); PostHasTransparency();
mHaveAlphaData = true;
} }
mUseAlphaData = mHaveAlphaData = true; mUseAlphaData = mHaveAlphaData = true;
mCurLine -= std::min<int32_t>(byte, mCurLine);
int32_t yDelta = std::min<int32_t>(byte, mCurLine);
mCurLine -= yDelta;
if (mDownscaler && yDelta > 0) {
// Commit the current row (the first of the skipped rows).
mDownscaler->CommitRow();
// Clear and commit the remaining skipped rows.
for (int32_t line = 1 ; line < yDelta ; ++line) {
mDownscaler->ClearRow();
mDownscaler->CommitRow();
}
}
break; break;
}
case eRLEStateAbsoluteMode: // Absolute Mode case eRLEStateAbsoluteMode: // Absolute Mode
case eRLEStateAbsoluteModePadded: case eRLEStateAbsoluteModePadded:
@ -845,9 +883,12 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// represents the number of pixels // represents the number of pixels
// that follow, each of which contains // that follow, each of which contains
// the color index of a single pixel. // the color index of a single pixel.
uint32_t* d = reinterpret_cast<uint32_t*> uint32_t* d = mDownscaler
(mImageData) + ? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
PIXEL_OFFSET(mCurLine, mCurPos); + mCurPos
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, mCurPos);
uint32_t* oldPos = d; uint32_t* oldPos = d;
if (mBIH.compression == BMPINFOHEADER::RLE8) { if (mBIH.compression == BMPINFOHEADER::RLE8) {
while (aCount > 0 && mStateData > 0) { while (aCount > 0 && mStateData > 0) {
@ -903,9 +944,15 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
const uint32_t rows = mOldLine - mCurLine; const uint32_t rows = mOldLine - mCurLine;
if (rows) { if (rows) {
// Invalidate // Invalidate
nsIntRect r(0, mBIH.height < 0 ? -mBIH.height - mOldLine : mCurLine, if (!mDownscaler) {
mBIH.width, rows); nsIntRect r(0, mBIH.height < 0 ? -mBIH.height - mOldLine : mCurLine,
PostInvalidation(r); mBIH.width, rows);
PostInvalidation(r);
} else if (mDownscaler->HasInvalidation()) {
DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
PostInvalidation(invalidRect.mOriginalSizeRect,
Some(invalidRect.mTargetSizeRect));
}
mOldLine = mCurLine; mOldLine = mCurLine;
} }

View File

@ -9,6 +9,7 @@
#include "BMPFileHeaders.h" #include "BMPFileHeaders.h"
#include "Decoder.h" #include "Decoder.h"
#include "Downscaler.h"
#include "gfxColor.h" #include "gfxColor.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
@ -24,6 +25,8 @@ class nsBMPDecoder : public Decoder
public: public:
~nsBMPDecoder(); ~nsBMPDecoder();
nsresult SetTargetSize(const nsIntSize& aSize) override;
// Specifies whether or not the BMP file will contain alpha data // Specifies whether or not the BMP file will contain alpha data
// If set to true and the BMP is 32BPP, the alpha data will be // If set to true and the BMP is 32BPP, the alpha data will be
// retrieved from the 4th byte of image data per pixel // retrieved from the 4th byte of image data per pixel
@ -46,7 +49,10 @@ public:
// Obtains whether or not a BMP file had alpha data in its 4th byte // Obtains whether or not a BMP file had alpha data in its 4th byte
// for 32BPP bitmaps. Only use after the bitmap has been processed. // for 32BPP bitmaps. Only use after the bitmap has been processed.
bool HasAlphaData() const; bool HasAlphaData() const { return mHaveAlphaData; }
/// Marks this BMP as having alpha data (due to e.g. an ICO alpha mask).
void SetHasAlphaData() { mHaveAlphaData = true; }
virtual void WriteInternal(const char* aBuffer, virtual void WriteInternal(const char* aBuffer,
uint32_t aCount) override; uint32_t aCount) override;
@ -71,6 +77,8 @@ private:
char mRawBuf[BIH_INTERNAL_LENGTH::WIN_V3]; //< If this is changed, char mRawBuf[BIH_INTERNAL_LENGTH::WIN_V3]; //< If this is changed,
// WriteInternal() MUST be updated // WriteInternal() MUST be updated
Maybe<Downscaler> mDownscaler;
uint32_t mLOH; //< Length of the header uint32_t mLOH; //< Length of the header
uint32_t mNumColors; //< The number of used colors, i.e. the number of uint32_t mNumColors; //< The number of used colors, i.e. the number of

View File

@ -532,14 +532,14 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// If the bitmap is fully processed, treat any left over data as the ICO's // If the bitmap is fully processed, treat any left over data as the ICO's
// 'AND buffer mask' which appears after the bitmap resource. // 'AND buffer mask' which appears after the bitmap resource.
if (!mIsPNG && mPos >= bmpDataEnd) { if (!mIsPNG && mPos >= bmpDataEnd) {
nsRefPtr<nsBMPDecoder> bmpDecoder =
static_cast<nsBMPDecoder*>(mContainedDecoder.get());
// There may be an optional AND bit mask after the data. This is // There may be an optional AND bit mask after the data. This is
// only used if the alpha data is not already set. The alpha data // only used if the alpha data is not already set. The alpha data
// is used for 32bpp bitmaps as per the comment in ICODecoder.h // is used for 32bpp bitmaps as per the comment in ICODecoder.h
// The alpha mask should be checked in all other cases. // The alpha mask should be checked in all other cases.
if (static_cast<nsBMPDecoder*>(mContainedDecoder.get())-> if (bmpDecoder->GetBitsPerPixel() != 32 || !bmpDecoder->HasAlphaData()) {
GetBitsPerPixel() != 32 ||
!static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
HasAlphaData()) {
uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
if (mPos == bmpDataEnd) { if (mPos == bmpDataEnd) {
mPos++; mPos++;
@ -573,9 +573,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mCurLine--; mCurLine--;
mRowBytes = 0; mRowBytes = 0;
uint32_t* imageData = uint32_t* imageData = bmpDecoder->GetImageData();
static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
GetImageData();
if (!imageData) { if (!imageData) {
PostDataError(); PostDataError();
return; return;
@ -601,7 +599,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// If any bits are set in sawTransparency, then we know at least one // If any bits are set in sawTransparency, then we know at least one
// pixel was transparent. // pixel was transparent.
if (sawTransparency) { if (sawTransparency) {
PostHasTransparency(); PostHasTransparency();
bmpDecoder->SetHasAlphaData();
} }
} }
} }

View File

@ -12,15 +12,20 @@
#include "RasterImage.h" #include "RasterImage.h"
#include <algorithm> #include <algorithm>
using namespace mozilla::gfx;
using std::min;
namespace mozilla { namespace mozilla {
namespace image { namespace image {
nsIconDecoder::nsIconDecoder(RasterImage* aImage) nsIconDecoder::nsIconDecoder(RasterImage* aImage)
: Decoder(aImage), : Decoder(aImage)
mWidth(-1), , mExpectedDataLength(0)
mHeight(-1), , mPixBytesRead(0)
mPixBytesRead(0), , mState(iconStateStart)
mState(iconStateStart) , mWidth(-1)
, mHeight(-1)
{ {
// Nothing to do // Nothing to do
} }
@ -28,15 +33,25 @@ nsIconDecoder::nsIconDecoder(RasterImage* aImage)
nsIconDecoder::~nsIconDecoder() nsIconDecoder::~nsIconDecoder()
{ } { }
nsresult
nsIconDecoder::SetTargetSize(const nsIntSize& aSize)
{
// Make sure the size is reasonable.
if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
return NS_ERROR_FAILURE;
}
// Create a downscaler that we'll filter our output through.
mDownscaler.emplace(aSize);
return NS_OK;
}
void void
nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
{ {
MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!"); MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!");
// We put this here to avoid errors about crossing initialization with case
// jumps on linux.
uint32_t bytesToRead = 0;
// Loop until the input data is gone // Loop until the input data is gone
while (aCount > 0) { while (aCount > 0) {
switch (mState) { switch (mState) {
@ -73,9 +88,16 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
break; break;
} }
// The input is 32bpp, so we expect 4 bytes of data per pixel.
mExpectedDataLength = mWidth * mHeight * 4;
{ {
MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); MOZ_ASSERT(!mImageData, "Already have a buffer allocated?");
nsresult rv = AllocateBasicFrame(); IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
: GetSize();
nsresult rv = AllocateFrame(0, targetSize,
IntRect(IntPoint(), targetSize),
gfx::SurfaceFormat::B8G8R8A8);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mState = iconStateFinished; mState = iconStateFinished;
return; return;
@ -84,6 +106,16 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
MOZ_ASSERT(mImageData, "Should have a buffer now"); MOZ_ASSERT(mImageData, "Should have a buffer now");
if (mDownscaler) {
nsresult rv = mDownscaler->BeginFrame(GetSize(),
mImageData,
/* aHasAlpha = */ true);
if (NS_FAILED(rv)) {
mState = iconStateFinished;
return;
}
}
// Book Keeping // Book Keeping
aBuffer++; aBuffer++;
aCount--; aCount--;
@ -93,25 +125,60 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case iconStateReadPixels: { case iconStateReadPixels: {
// How many bytes are we reading? // How many bytes are we reading?
bytesToRead = std::min(aCount, mImageDataLength - mPixBytesRead); uint32_t bytesToRead = min(aCount, mExpectedDataLength - mPixBytesRead);
// Copy the bytes if (mDownscaler) {
memcpy(mImageData + mPixBytesRead, aBuffer, bytesToRead); uint8_t* row = mDownscaler->RowBuffer();
const uint32_t bytesPerRow = mWidth * 4;
const uint32_t rowOffset = mPixBytesRead % bytesPerRow;
// Performance isn't critical here, so our update rectangle is // Update global state; we're about to read |bytesToRead| bytes.
// always the full icon aCount -= bytesToRead;
nsIntRect r(0, 0, mWidth, mHeight); mPixBytesRead += bytesToRead;
// Invalidate if (rowOffset > 0) {
PostInvalidation(r); // Finish the current row.
const uint32_t remaining = bytesPerRow - rowOffset;
memcpy(row + rowOffset, aBuffer, remaining);
aBuffer += remaining;
bytesToRead -= remaining;
mDownscaler->CommitRow();
}
// Book Keeping // Copy the bytes a row at a time.
aBuffer += bytesToRead; while (bytesToRead > bytesPerRow) {
aCount -= bytesToRead; memcpy(row, aBuffer, bytesPerRow);
mPixBytesRead += bytesToRead; aBuffer += bytesPerRow;
bytesToRead -= bytesPerRow;
mDownscaler->CommitRow();
}
// Copy any leftover bytes. (Leaving the current row incomplete.)
if (bytesToRead > 0) {
memcpy(row, aBuffer, bytesToRead);
aBuffer += bytesPerRow;
bytesToRead -= bytesPerRow;
}
if (mDownscaler->HasInvalidation()) {
DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
PostInvalidation(invalidRect.mOriginalSizeRect,
Some(invalidRect.mTargetSizeRect));
}
} else {
// Copy all the bytes at once.
memcpy(mImageData + mPixBytesRead, aBuffer, bytesToRead);
aBuffer += bytesToRead;
aCount -= bytesToRead;
mPixBytesRead += bytesToRead;
// Invalidate. Performance isn't critical here, so our update
// rectangle is always the full icon.
PostInvalidation(IntRect(0, 0, mWidth, mHeight));
}
// If we've got all the pixel bytes, we're finished // If we've got all the pixel bytes, we're finished
if (mPixBytesRead == mImageDataLength) { if (mPixBytesRead == mExpectedDataLength) {
PostFrameStop(); PostFrameStop();
PostDecodeDone(); PostDecodeDone();
mState = iconStateFinished; mState = iconStateFinished;

View File

@ -39,6 +39,8 @@ class nsIconDecoder : public Decoder
public: public:
virtual ~nsIconDecoder(); virtual ~nsIconDecoder();
virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override; virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
private: private:
@ -47,11 +49,13 @@ private:
// Decoders should only be instantiated via DecoderFactory. // Decoders should only be instantiated via DecoderFactory.
explicit nsIconDecoder(RasterImage* aImage); explicit nsIconDecoder(RasterImage* aImage);
public: Maybe<Downscaler> mDownscaler;
uint8_t mWidth;
uint8_t mHeight; uint32_t mExpectedDataLength;
uint32_t mPixBytesRead; uint32_t mPixBytesRead;
uint32_t mState; uint32_t mState;
uint8_t mWidth;
uint8_t mHeight;
}; };
enum { enum {

View File

@ -1314,6 +1314,7 @@ if test "$GNU_CXX"; then
# -Wparentheses - catches `if (a=b)` and operator precedence bugs # -Wparentheses - catches `if (a=b)` and operator precedence bugs
# -Wpointer-arith - catches pointer arithmetic using NULL or sizeof(void) # -Wpointer-arith - catches pointer arithmetic using NULL or sizeof(void)
# -Wpointer-to-int-cast - catches casts from pointer to different sized int # -Wpointer-to-int-cast - catches casts from pointer to different sized int
# -Wrange-loop-analysis - catches copies during range-based for loops.
# -Wreorder - catches ctor initializer list not matching class definition order # -Wreorder - catches ctor initializer list not matching class definition order
# -Wreturn-type - catches missing returns, zero false positives # -Wreturn-type - catches missing returns, zero false positives
# -Wsequence-point - catches undefined order behavior like `a = a++` # -Wsequence-point - catches undefined order behavior like `a = a++`
@ -1354,6 +1355,7 @@ if test "$GNU_CXX"; then
MOZ_CXX_SUPPORTS_WARNING(-Werror=, conversion-null, ac_cxx_has_werror_conversion_null) MOZ_CXX_SUPPORTS_WARNING(-Werror=, conversion-null, ac_cxx_has_werror_conversion_null)
MOZ_CXX_SUPPORTS_WARNING(-Werror=, non-literal-null-conversion, ac_cxx_has_werror_non_literal_null_conversion) MOZ_CXX_SUPPORTS_WARNING(-Werror=, non-literal-null-conversion, ac_cxx_has_werror_non_literal_null_conversion)
MOZ_CXX_SUPPORTS_WARNING(-Werror=, range-loop-analysis, ac_cxx_has_range_loop_analysis)
MOZ_CXX_SUPPORTS_WARNING(-Werror=, sometimes-uninitialized, ac_cxx_has_sometimes_uninitialized) MOZ_CXX_SUPPORTS_WARNING(-Werror=, sometimes-uninitialized, ac_cxx_has_sometimes_uninitialized)
fi fi

View File

@ -2620,7 +2620,8 @@ NS_IMETHODIMP nsDocumentViewer::SelectAll()
NS_IMETHODIMP nsDocumentViewer::CopySelection() NS_IMETHODIMP nsDocumentViewer::CopySelection()
{ {
nsCopySupport::FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, mPresShell, nullptr); nsCopySupport::FireClipboardEvent(eCopy, nsIClipboard::kGlobalClipboard,
mPresShell, nullptr);
return NS_OK; return NS_OK;
} }

View File

@ -5320,7 +5320,7 @@ bool PresShell::AsyncPanZoomEnabled()
return widget->AsyncPanZoomEnabled(); return widget->AsyncPanZoomEnabled();
} }
} }
return false; return gfxPlatform::AsyncPanZoomEnabled();
} }
void PresShell::SetIgnoreViewportScrolling(bool aIgnore) void PresShell::SetIgnoreViewportScrolling(bool aIgnore)

View File

@ -371,6 +371,11 @@ CommonAnimationManager::FlushAnimations()
continue; continue;
} }
MOZ_ASSERT(collection->mElement->GetComposedDoc() ==
mPresContext->Document(),
"Should not have a transition/animations collection for an "
"element that is not part of the document tree");
collection->RequestRestyle(AnimationCollection::RestyleType::Standard); collection->RequestRestyle(AnimationCollection::RestyleType::Standard);
} }
} }
@ -883,10 +888,6 @@ AnimationCollection::RequestRestyle(RestyleType aRestyleType)
return; return;
} }
MOZ_ASSERT(mElement->GetCrossShadowCurrentDoc() == presContext->Document(),
"Element::UnbindFromTree should have destroyed the element "
"transition/animations object");
// Steps for Restyle::Layer: // Steps for Restyle::Layer:
if (aRestyleType == RestyleType::Layer) { if (aRestyleType == RestyleType::Layer) {

View File

@ -0,0 +1,16 @@
<!doctype html>
<html>
<head>
<style>
.anim { animation: anim 2s infinite linear }
@keyframes anim { }
</style>
</head>
<body>
<script>
var i = document.createElement('i');
i.setAttribute('class', 'anim');
getComputedStyle(i).display;
</script>
</body>
</html>

View File

@ -120,5 +120,6 @@ load 1161366-1.html
load 1163446-1.html load 1163446-1.html
load 1164813-1.html load 1164813-1.html
load 1167782-1.html load 1167782-1.html
load 1200568-1.html
load large_border_image_width.html load large_border_image_width.html
load border-image-visited-link.html load border-image-visited-link.html

View File

@ -371,8 +371,9 @@ nsIStyleRule*
nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
mozilla::dom::Element* aElement) mozilla::dom::Element* aElement)
{ {
if (!mPresContext->IsDynamic()) { // Ignore animations for print or print preview, and for elements
// For print or print preview, ignore animations. // that are not attached to the document tree.
if (!mPresContext->IsDynamic() || !aElement->IsInComposedDoc()) {
return nullptr; return nullptr;
} }

Some files were not shown because too many files have changed in this diff Show More