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
# 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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

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

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

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

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e69f2c86b931b723dd405115e33a1d02e6c5f5e6"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="60e212543329ee48f2921e0cd92aaca4b4ce2f6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
html {
font: message-box;
font-size: 12px;
font-size: 11px;
font-weight: 400;
}
@ -53,42 +53,59 @@ label,
position: relative;
}
.panel-item span {
display: block;
float: left;
overflow: hidden;
text-overflow: ellipsis;
width: 75%;
white-space: nowrap;
}
.panel-item {
padding: 3%;
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%;
cursor: pointer;
border-top: 1px solid transparent;
border-left: 0;
border-bottom: 1px solid #CCC;
border-right: 0;
background-color: transparent;
}
button.panel-item {
background-position: 8px 8px;
background-position: 5px 5px;
background-repeat: no-repeat;
background-size: 14px 14px;
padding-left: 25px;
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 {
background-color: #FFF;
color: #5A5A5A;
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;
border-top: 1px solid #EDEDED;
}
.configure-button {
@ -101,7 +118,7 @@ button.project-panel-item-refreshtabs {
background-repeat: no-repeat;
background-size: 14px 14px;
position: absolute;
top: 0;
top: -2px;
right: 0;
border: 0;
}

View File

@ -162,10 +162,14 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
.panel-list {
display: none;
position: relative;
max-width: 250px;
max-width: 180px;
overflow: hidden;
}
#project-listing-panel.panel-list {
max-width: 165px;
}
.panel-list-wrapper {
height: 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)
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
# corresponding the make target
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/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.
AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1

View File

@ -8,7 +8,12 @@
# to be set:
# UPLOAD_HOST : host to upload files to
# UPLOAD_USER : username on that host
# and one of the following:
# 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:
# UPLOAD_SSH_KEY : path to a ssh private key to use
@ -25,18 +30,12 @@
import sys, os
import re
import json
import errno
import hashlib
from optparse import OptionParser
from subprocess import check_call, check_output, STDOUT
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):
"""Return the value of the environment variable named v, or None
if it's unset (or empty)."""
@ -119,6 +118,33 @@ def GetRemotePath(path, local_file, base_path):
dir = dir[len(base_path)+1:].replace('\\','/')
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):
# let's create a switch case using name-spaces/dict
# 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}
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
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
@ -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
all files uploaded.
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:
path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
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:
base_path = os.path.abspath(base_path)
remote_files = []
properties = {}
try:
for file in files:
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)
# We print since mozharness may parse URLs from the output stream.
print output
if properties_file:
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)
properties = GetUrlProperties(output, package)
finally:
if upload_to_temp_dir:
DoSSHCommand("rm -rf %s" % path, user, host, port=port,
ssh_key=ssh_key)
if verbose:
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__':
host = RequireEnvironmentVariable('UPLOAD_HOST')
user = RequireEnvironmentVariable('UPLOAD_USER')
host = OptionalEnvironmentVariable('UPLOAD_HOST')
user = OptionalEnvironmentVariable('UPLOAD_USER')
path = OptionalEnvironmentVariable('UPLOAD_PATH')
upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
port = OptionalEnvironmentVariable('UPLOAD_PORT')
@ -216,10 +256,7 @@ if __name__ == '__main__':
port = int(port)
key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
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 path is not None:
path = FixupMsysPath(path)
@ -240,12 +277,16 @@ if __name__ == '__main__':
if len(args) < 1:
print "You must specify at least one file to upload"
sys.exit(1)
if not options.properties_file:
print "You must specify a --properties-file"
sys.exit(1)
try:
UploadFiles(user, host, path, args, base_path=options.base_path,
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
post_upload_command=post_upload_command,
properties_file=options.properties_file, package=options.package,
verbose=True)
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,
post_upload_command=post_upload_command,
package=options.package,
verbose=True)
WriteProperties(args, options.properties_file, url_properties, options.package)
except IOError, (strerror):
print strerror
sys.exit(1)

View File

@ -1595,6 +1595,7 @@ if test "$GNU_CXX"; then
# -Woverloaded-virtual - function declaration hides virtual function from base class
# -Wparentheses - catches `if (a=b)` and operator precedence bugs
# -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
# -Wsequence-point - catches undefined order behavior like `a = a++`
# -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"
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)
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*
ExplicitChildIterator::Get()
{

View File

@ -60,16 +60,24 @@ public:
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
// whether aChildToFind was found as an explicit child prior to encountering
// 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
// we might not find aChildToFind when called from ContentInserted
// 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;
do {
child = GetNextChild();

View File

@ -316,7 +316,7 @@ ShadowRoot::DistributeSingleNode(nsIContent* aContent)
if (!isIndexFound) {
// We have still not found an index in the insertion point,
// 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");
insertionPoint->AppendMatchedNode(aContent);
}

View File

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

View File

@ -631,8 +631,8 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
*aActionTaken = false;
}
NS_ASSERTION(aEventMessage == NS_CUT || aEventMessage == NS_COPY ||
aEventMessage == NS_PASTE,
NS_ASSERTION(aEventMessage == eCut || aEventMessage == eCopy ||
aEventMessage == ePaste,
"Invalid clipboard event type");
nsCOMPtr<nsIPresShell> presShell = aPresShell;
@ -688,7 +688,7 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
nsRefPtr<DataTransfer> clipboardData;
if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
clipboardData =
new DataTransfer(piWindow, aEventMessage, aEventMessage == NS_PASTE,
new DataTransfer(piWindow, aEventMessage, aEventMessage == ePaste,
aClipboardType);
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
// took care of it and cancelled the event, or the caller will handle it.
// 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
// from reading the clipboard contents after the paste event has fired.
if (clipboardData) {
@ -743,7 +743,7 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
// when cutting non-editable content, do nothing
// 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
bool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);

View File

@ -64,8 +64,8 @@ class nsCopySupport
/**
* 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
* NS_PASTE, and perform the default copy action if the event was not
* on the value of aEventMessage, which should be either eCut, eCopy or
* ePaste, and perform the default copy action if the event was not
* cancelled.
*
* 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;
}
WidgetSelectionEvent selectionEvent(true, NS_SELECTION_SET, widget);
WidgetSelectionEvent selectionEvent(true, eSetSelection, widget);
InitEvent(selectionEvent);
selectionEvent.mOffset = aOffset;

View File

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

View File

@ -6918,7 +6918,9 @@ nsGlobalWindow::AlertOrConfirm(bool aAlert,
MOZ_ASSERT(IsOuterWindow());
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;
}
@ -7058,7 +7060,7 @@ nsGlobalWindow::PromptOuter(const nsAString& aMessage, const nsAString& aInitial
SetDOMStringToNull(aReturn);
if (!AreDialogsEnabled()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE);
// Return null, as if the user just canceled the prompt.
return;
}
@ -7496,6 +7498,8 @@ nsGlobalWindow::PrintOuter(ErrorResult& aError)
}
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);
return;
}
@ -9553,6 +9557,8 @@ nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgumen
EnsureReflowFlushAndPaint();
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);
return nullptr;
}

View File

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

View File

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

View File

@ -1295,11 +1295,11 @@ BluetoothAdapter::HandlePullVCardListingReq(const BluetoothValue& aValue)
if (name.EqualsLiteral("name")) {
init.mName = value.get_nsString();
} 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")) {
init.mSearchValue = value.get_nsString();
} else if (name.EqualsLiteral("searchKey")) {
init.mSearchKey = ConvertStringToVCardSearchKeyType(value.get_nsString());
} else if (name.EqualsLiteral("maxListCount")) {
init.mMaxListCount = value.get_uint32_t();
} else if (name.EqualsLiteral("listStartOffset")) {
@ -1338,40 +1338,6 @@ BluetoothAdapter::getVCardProperties(const BluetoothValue &aValue)
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
BluetoothAdapter::DispatchAttributeEvent(const Sequence<nsString>& aTypes)
{

View File

@ -342,21 +342,6 @@ private:
*/
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.
*

View File

@ -79,7 +79,7 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
// 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
// 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);
}
}
@ -105,11 +105,11 @@ ClipboardEvent::GetClipboardData()
if (!event->clipboardData) {
if (mEventIsInternal) {
event->clipboardData =
new DataTransfer(ToSupports(this), NS_COPY, false, -1);
new DataTransfer(ToSupports(this), eCopy, false, -1);
} else {
event->clipboardData =
new DataTransfer(ToSupports(this), event->mMessage,
event->mMessage == NS_PASTE,
event->mMessage == ePaste,
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
// clear the readonly state. Otherwise, the data is already present. For
// external usage, cache the data from the native clipboard or drag.
if (aEventMessage == NS_CUT ||
aEventMessage == NS_COPY ||
if (aEventMessage == eCut ||
aEventMessage == eCopy ||
aEventMessage == eDragStart ||
aEventMessage == eLegacyDragGesture) {
mReadOnly = false;
} else if (mIsExternal) {
if (aEventMessage == NS_PASTE) {
if (aEventMessage == ePaste) {
CacheExternalClipboardFormats();
} else if (aEventMessage >= eDragDropEventFirst &&
aEventMessage <= eDragDropEventLast) {
@ -271,7 +271,7 @@ DataTransfer::GetFiles(ErrorResult& aRv)
{
if (mEventMessage != eDrop &&
mEventMessage != eLegacyDragDrop &&
mEventMessage != NS_PASTE) {
mEventMessage != ePaste) {
return nullptr;
}
@ -543,8 +543,8 @@ DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv)
{
// Only the first item is valid for clipboard events
if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY ||
mEventMessage == NS_PASTE)) {
(mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == ePaste)) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
@ -584,8 +584,8 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
// Only the first item is valid for clipboard events
if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY ||
mEventMessage == NS_PASTE)) {
(mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == ePaste)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
@ -604,7 +604,7 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* principal = nullptr;
if (mIsCrossDomainSubFrameDrop ||
(mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
mEventMessage != NS_PASTE &&
mEventMessage != ePaste &&
!nsContentUtils::IsCallerChrome())) {
principal = nsContentUtils::SubjectPrincipal();
}
@ -696,8 +696,8 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
// Only the first item is valid for clipboard events
if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY ||
mEventMessage == NS_PASTE)) {
(mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == ePaste)) {
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
if (aIndex > 0 &&
(mEventMessage == NS_CUT || mEventMessage == NS_COPY ||
mEventMessage == NS_PASTE)) {
(mEventMessage == eCut || mEventMessage == eCopy ||
mEventMessage == ePaste)) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
@ -758,8 +758,8 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(!mReadOnly);
MOZ_ASSERT(aIndex < mItems.Length());
MOZ_ASSERT(aIndex == 0 ||
(mEventMessage != NS_CUT && mEventMessage != NS_COPY &&
mEventMessage != NS_PASTE));
(mEventMessage != eCut && mEventMessage != eCopy &&
mEventMessage != ePaste));
nsAutoString format;
GetRealFormat(aFormat, format);
@ -1258,7 +1258,7 @@ DataTransfer::CacheExternalDragFormats()
void
DataTransfer::CacheExternalClipboardFormats()
{
NS_ASSERTION(mEventMessage == NS_PASTE,
NS_ASSERTION(mEventMessage == ePaste,
"caching clipboard data for invalid event");
// 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
NS_ASSERTION(mEventMessage != NS_CUT && mEventMessage != NS_COPY,
NS_ASSERTION(mEventMessage != eCut && mEventMessage != eCopy,
"clipboard event with empty data");
NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
@ -1318,7 +1318,7 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
trans->Init(nullptr);
trans->AddDataFlavor(format);
if (mEventMessage == NS_PASTE) {
if (mEventMessage == ePaste) {
MOZ_ASSERT(aIndex == 0, "index in clipboard must be 0");
nsCOMPtr<nsIClipboard> clipboard = do_GetService("@mozilla.org/widget/clipboard;1");

View File

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

View File

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

View File

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

View File

@ -291,14 +291,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
nsRefPtr<MediaDecoderStateMachine> self = this;
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);
mMediaSink = CreateAudioSink();
}
MediaDecoderStateMachine::~MediaDecoderStateMachine()
@ -348,6 +341,19 @@ MediaDecoderStateMachine::InitializationTask()
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()
{
MOZ_ASSERT(OnTaskQueue());
@ -377,7 +383,7 @@ int64_t MediaDecoderStateMachine::GetDecodedAudioDuration()
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
int64_t audioDecoded = AudioQueue().Duration();
if (mAudioSink->IsStarted()) {
if (mMediaSink->IsStarted()) {
audioDecoded += AudioEndTime() - GetMediaTime();
}
return audioDecoded;
@ -387,7 +393,6 @@ void MediaDecoderStateMachine::DiscardStreamData()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
MOZ_ASSERT(!mAudioSink->IsStarted(), "Should've been stopped in RunStateMachine()");
const auto clockTime = GetClock();
while (true) {
@ -1077,8 +1082,7 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
SetPlayStartTime(TimeStamp::Now());
MOZ_ASSERT(IsPlaying());
StartAudioSink();
StartDecodedStream();
StartMediaSink();
DispatchDecodeTasksIfNeeded();
}
@ -1152,8 +1156,7 @@ void MediaDecoderStateMachine::VolumeChanged()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mAudioSink->SetVolume(mVolume);
mStreamSink->SetVolume(mVolume);
mMediaSink->SetVolume(mVolume);
}
void MediaDecoderStateMachine::RecomputeDuration()
@ -1273,7 +1276,7 @@ void MediaDecoderStateMachine::Shutdown()
Reset();
mAudioSink->Shutdown();
mMediaSink->Shutdown();
// Shut down our start time rendezvous.
if (mStartTimeRendezvous) {
@ -1466,15 +1469,15 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
return mPendingSeek.mPromise.Ensure(__func__);
}
void MediaDecoderStateMachine::StopAudioSink()
void MediaDecoderStateMachine::StopMediaSink()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mAudioSink->IsStarted()) {
DECODER_LOG("Stop AudioSink");
mAudioSink->Stop();
mAudioSinkPromise.DisconnectIfExists();
if (mMediaSink->IsStarted()) {
DECODER_LOG("Stop MediaSink");
mMediaSink->Stop();
mMediaSinkPromise.DisconnectIfExists();
}
}
@ -1752,59 +1755,25 @@ MediaDecoderStateMachine::RequestVideoData()
}
void
MediaDecoderStateMachine::StartAudioSink()
MediaDecoderStateMachine::StartMediaSink()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mAudioCaptured) {
MOZ_ASSERT(!mAudioSink->IsStarted());
return;
}
if (!mAudioSink->IsStarted()) {
if (!mMediaSink->IsStarted()) {
mAudioCompleted = false;
mAudioSink->Start(GetMediaTime(), mInfo);
mMediaSink->Start(GetMediaTime(), mInfo);
auto promise = mAudioSink->OnEnded(TrackInfo::kAudioTrack);
auto promise = mMediaSink->OnEnded(TrackInfo::kAudioTrack);
if (promise) {
mAudioSinkPromise.Begin(promise->Then(
mMediaSinkPromise.Begin(promise->Then(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioSinkComplete,
&MediaDecoderStateMachine::OnAudioSinkError));
&MediaDecoderStateMachine::OnMediaSinkComplete,
&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()
{
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
// already decoded and pushed to the hardware, plus the amount of audio
// 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
// wrong values (Bug 1114434), so we use frame counts to calculate duration.
@ -1842,7 +1811,7 @@ bool MediaDecoderStateMachine::OutOfDecodedAudio()
MOZ_ASSERT(OnTaskQueue());
return IsAudioDecoding() && !AudioQueue().IsFinished() &&
AudioQueue().GetSize() == 0 &&
!mAudioSink->HasUnplayedFrames(TrackInfo::kAudioTrack);
!mMediaSink->HasUnplayedFrames(TrackInfo::kAudioTrack);
}
bool MediaDecoderStateMachine::HasLowUndecodedData()
@ -2416,8 +2385,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
mSentPlaybackEndedEvent = true;
// MediaSink::GetEndTime() must be called before stopping playback.
StopAudioSink();
StopDecodedStream();
StopMediaSink();
}
return NS_OK;
@ -2443,11 +2411,10 @@ MediaDecoderStateMachine::Reset()
mState == DECODER_STATE_DORMANT ||
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
// crash for no samples to be popped.
StopAudioSink();
StopDecodedStream();
StopMediaSink();
mVideoFrameEndTime = -1;
mDecodedVideoEndTime = -1;
@ -2585,11 +2552,7 @@ int64_t MediaDecoderStateMachine::GetClock(TimeStamp* aTimeStamp) const
if (!IsPlaying()) {
clock_time = mPlayDuration;
} else {
if (mAudioCaptured) {
clock_time = mStreamSink->GetPosition(&t);
} else {
clock_time = mAudioSink->GetPosition(&t);
}
clock_time = mMediaSink->GetPosition(&t);
NS_ASSERTION(GetMediaTime() <= clock_time, "Clock should go forwards.");
}
if (aTimeStamp) {
@ -2879,9 +2842,7 @@ void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp)
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
mPlayStartTime = aTimeStamp;
mAudioSink->SetPlaying(!mPlayStartTime.IsNull());
mStreamSink->SetPlaying(!mPlayStartTime.IsNull());
mMediaSink->SetPlaying(!mPlayStartTime.IsNull());
}
void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
@ -2959,7 +2920,7 @@ MediaDecoderStateMachine::LogicalPlaybackRateChanged()
}
mPlaybackRate = mLogicalPlaybackRate;
mAudioSink->SetPlaybackRate(mPlaybackRate);
mMediaSink->SetPlaybackRate(mPlaybackRate);
ScheduleStateMachine();
}
@ -2968,7 +2929,7 @@ void MediaDecoderStateMachine::PreservesPitchChanged()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mAudioSink->SetPreservesPitch(mPreservesPitch);
mMediaSink->SetPreservesPitch(mPreservesPitch);
}
bool MediaDecoderStateMachine::IsShutdown()
@ -2982,33 +2943,33 @@ MediaDecoderStateMachine::AudioEndTime() const
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mAudioSink->IsStarted()) {
return mAudioSink->GetEndTime(TrackInfo::kAudioTrack);
} else if (mAudioCaptured) {
return mStreamSink->GetEndTime(TrackInfo::kAudioTrack);
if (mMediaSink->IsStarted()) {
return mMediaSink->GetEndTime(TrackInfo::kAudioTrack);
}
MOZ_ASSERT(!HasAudio());
return -1;
}
void MediaDecoderStateMachine::OnAudioSinkComplete()
void MediaDecoderStateMachine::OnMediaSinkComplete()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete();
mAudioCompleted = true;
mMediaSinkPromise.Complete();
// 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());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete();
mAudioCompleted = true;
mMediaSinkPromise.Complete();
// Set true only when we have audio.
mAudioCompleted = mInfo.HasAudio();
// Make the best effort to continue playback when there is video.
if (HasVideo()) {
@ -3021,31 +2982,41 @@ void MediaDecoderStateMachine::OnAudioSinkError()
}
void
MediaDecoderStateMachine::OnDecodedStreamFinish()
MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(mAudioCaptured, "Audio should be captured.");
mDecodedStreamPromise.Complete();
if (mInfo.HasAudio()) {
mAudioCompleted = true;
if (aCaptured == mAudioCaptured) {
return;
}
// 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();
}
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
{
MOZ_ASSERT(OnTaskQueue());
@ -3055,55 +3026,15 @@ uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
: 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,
bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
mStreamSink->AddOutput(aStream, aFinishWhenEnded);
DispatchAudioCaptured();
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &MediaDecoderStateMachine::SetAudioCaptured, true);
OwnerThread()->Dispatch(r.forget());
}
void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
@ -3112,7 +3043,9 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
DECODER_LOG("RemoveOutputStream=%p!", aStream);
mStreamSink->RemoveOutput(aStream);
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.
void InitializationTask();
void DispatchAudioCaptured();
void DispatchAudioUncaptured();
void SetAudioCaptured(bool aCaptured);
void Shutdown();
public:
@ -489,19 +488,17 @@ protected:
// state machine thread.
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.
// 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.
// Called on the state machine thread.
void StartAudioSink();
void StopDecodedStream();
void StartDecodedStream();
void StartMediaSink();
// Notification method invoked when mPlayState changes.
void PlayStateChanged();
@ -648,16 +645,12 @@ protected:
void SetPlayStartTime(const TimeStamp& aTimeStamp);
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.
void OnAudioSinkComplete();
void OnMediaSinkComplete();
// Rejected by the AudioSink to signal errors.
void OnAudioSinkError();
void OnDecodedStreamFinish();
void OnDecodedStreamError();
// Rejected by the MediaSink to signal errors.
void OnMediaSinkError();
// Return true if the video decoder's decode speed can not catch up the
// play time.
@ -977,15 +970,15 @@ private:
// Media Fragment end time in microseconds. Access controlled by decoder monitor.
int64_t mFragmentEndTime;
// The audio sink resource. Used on the state machine thread.
nsRefPtr<media::MediaSink> mAudioSink;
// The media sink resource. Used on the state machine thread.
nsRefPtr<media::MediaSink> mMediaSink;
// The reader, don't call its methods with the decoder monitor held.
// This is created in the state machine's constructor.
nsRefPtr<MediaDecoderReader> mReader;
// The end time of the last audio frame that's been pushed onto the audio sink
// or DecodedStream in microseconds. This will approximately be the end time
// The end time of the last audio frame that's been pushed onto the media sink
// in microseconds. This will approximately be the end time
// of the audio stream, unless another frame is pushed to the hardware.
int64_t AudioEndTime() const;
@ -1270,8 +1263,7 @@ private:
// Media data resource from the decoder.
nsRefPtr<MediaResource> mResource;
MozPromiseRequestHolder<GenericPromise> mAudioSinkPromise;
MozPromiseRequestHolder<GenericPromise> mDecodedStreamPromise;
MozPromiseRequestHolder<GenericPromise> mMediaSinkPromise;
MediaEventListener mAudioQueueListener;
MediaEventListener mVideoQueueListener;

View File

@ -12,7 +12,7 @@
SimpleTest.waitForExplicitFinish();
// 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 = [
// Not the same origin no CORS asked for, should have silence

View File

@ -36,6 +36,9 @@
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "xpcpublic.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
namespace mozilla {
namespace dom {
@ -536,10 +539,10 @@ Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32());
if (task == PromiseCallback::Resolve) {
promise->MaybeResolveInternal(aCx, args.get(0));
if (!promise->CaptureStack(aCx, promise->mFullfillmentStack)) {
return false;
}
promise->MaybeResolveInternal(aCx, args.get(0));
} else {
promise->MaybeRejectInternal(aCx, args.get(0));
if (!promise->CaptureStack(aCx, promise->mRejectionStack)) {
@ -1342,6 +1345,29 @@ Promise::RejectInternal(JSContext* aCx,
void
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()) {
return;
}

View File

@ -628,7 +628,6 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
// The "Access-Control-Allow-Headers" header contains a comma separated
// list of header names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
headerVal);
nsTArray<nsCString> headers;
@ -1130,7 +1129,6 @@ nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
// The "Access-Control-Allow-Methods" header contains a comma separated
// list of method names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
headerVal);
@ -1161,7 +1159,6 @@ nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
// The "Access-Control-Allow-Headers" header contains a comma separated
// list of method names.
headerVal.Truncate();
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
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 <hardware/gps.h>
#include "GeolocationUtil.h"
#include "mozstumbler/MozStumbler.h"
#include "mozilla/Constants.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
@ -88,71 +90,6 @@ AGpsCallbacks GonkGPSGeolocationProvider::mAGPSCallbacks;
AGpsRilCallbacks GonkGPSGeolocationProvider::mAGPSRILCallbacks;
#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
GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
@ -211,35 +148,7 @@ GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
nsRefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
NS_DispatchToMainThread(event);
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(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");
}
}
MozStumble(somewhere);
}
void

View File

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

View File

@ -5,12 +5,22 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MozStumbler.h"
#include "nsDataHashtable.h"
#include "nsGeoPosition.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h"
#include "StumblerLogging.h"
#include "WriteStumbleOnThread.h"
#include "nsNetCID.h"
#include "nsDataHashtable.h"
#include "../GeolocationUtil.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::dom;
@ -18,6 +28,101 @@ using namespace mozilla::dom;
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
StumblerInfo::SetWifiInfoResponseReceived()
{

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,8 @@
#include "mozilla/Atomics.h"
class DeleteRunnable;
/*
This class is the entry point to stumbling, in that it
receives the location+cell+wifi string and writes it
@ -43,10 +45,13 @@ public:
NS_IMETHODIMP Run() override;
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:
friend class DeleteRunnable;
enum class Partition {
Begining,
@ -71,6 +76,8 @@ private:
// Only run one instance of this
static mozilla::Atomic<bool> sIsAlreadyRunning;
static mozilla::Atomic<bool> sIsFileWaitingForUpload;
// Limit the upload attempts per day. If the device is rebooted
// this resets the allowed attempts, which is acceptable.
struct UploadFreqGuard {

View File

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

View File

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

View File

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

View File

@ -1323,8 +1323,9 @@ bool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
NS_IMETHODIMP nsHTMLEditor::Paste(int32_t aSelectionType)
{
if (!FireClipboardEvent(NS_PASTE, aSelectionType))
if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK;
}
// Get Clipboard Service
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
// 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;
}
// handle transferable hooks
nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
@ -1424,8 +1426,9 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
//
NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(int32_t aSelectionType)
{
if (!FireClipboardEvent(NS_PASTE, aSelectionType))
if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK;
}
ForceCompositionEnd();

View File

@ -322,8 +322,9 @@ nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
NS_IMETHODIMP nsPlaintextEditor::Paste(int32_t aSelectionType)
{
if (!FireClipboardEvent(NS_PASTE, aSelectionType))
if (!FireClipboardEvent(ePaste, aSelectionType)) {
return NS_OK;
}
// Get Clipboard Service
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
// 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;
}
if (!IsModifiable())
return NS_OK;

View File

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

View File

@ -629,6 +629,12 @@ FilterNodeSoftware::GetOutput(const IntRect &aRect)
void
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);
RequestFromInputsForRect(aRect);
}

View File

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

View File

@ -347,6 +347,12 @@ FilterCachedColorModels::WrapForColorModel(ColorModel aColorModel)
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 == 1, aToMatrix is returned.
// 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,
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);
float oneMinusAmount = 1 - aAmount;
@ -392,12 +392,6 @@ static nsresult
ComputeColorMatrix(uint32_t aColorMatrixType, const nsTArray<float>& aValues,
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.
static const float lumR = 0.2126f;
static const float lumG = 0.7152f;
@ -760,7 +754,8 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
float colorMatrix[20];
uint32_t type = atts.GetUint(eColorMatrixType);
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]);
return filter.forget();
}
@ -954,11 +949,15 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
RefPtr<FilterNode> filter;
uint32_t op = atts.GetUint(eCompositeOperator);
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);
if (!filter) {
// All-zero coefficients sometimes occur in junk filters.
if (!filter ||
(coefficients.Length() == ArrayLength(allZero) &&
PodEqual(coefficients.Elements(), allZero, ArrayLength(allZero)))) {
return nullptr;
}
const nsTArray<float>& coefficients = atts.GetFloats(eCompositeCoefficients);
filter->SetAttribute(ATT_ARITHMETIC_COMBINE_COEFFICIENTS,
coefficients.Elements(), coefficients.Length());
filter->SetInput(IN_ARITHMETIC_COMBINE_IN, aSources[0]);

View File

@ -22,7 +22,6 @@
#endif
#include <string.h> // for memset
#include "gfxCore.h" // for NS_GFX
#include "mozilla/Scoped.h" // for SCOPED_TEMPLATE
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
* 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:
// 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__
#define gfxCrashReporterUtils_h__
#include "gfxCore.h"
namespace mozilla {
@ -21,7 +20,7 @@ namespace mozilla {
* 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.
*/
class NS_GFX ScopedGfxFeatureReporter
class ScopedGfxFeatureReporter
{
public:
explicit ScopedGfxFeatureReporter(const char *aFeature, bool force = false)

View File

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

View File

@ -75,8 +75,7 @@ static int ComponentValue(const char16_t* aColorSpec, int aLen, int color, int d
return component;
}
NS_GFX_(bool) NS_HexToRGB(const nsAString& aColorSpec,
nscolor* aResult)
bool NS_HexToRGB(const nsAString& aColorSpec, nscolor* aResult)
{
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
// 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")) {
return false;
@ -185,7 +184,7 @@ NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
return true;
}
NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
bool NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
{
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
// *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);
return kColorNames;
@ -215,7 +214,7 @@ NS_GFX_(const char * const *) NS_AllColorNames(size_t *aSizeArray)
#define MOZ_BLEND(target, bg, fg, fgalpha) \
FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
NS_GFX_(nscolor)
nscolor
NS_ComposeColors(nscolor aBG, nscolor aFG)
{
// 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
NS_GFX_(nscolor)
nscolor
NS_HSL2RGB(float h, float s, float l)
{
uint8_t r, g, b;
@ -281,7 +280,7 @@ NS_HSL2RGB(float h, float s, float l)
return NS_RGB(r, g, b);
}
NS_GFX_(const char*)
const char*
NS_RGBToColorName(nscolor aColor)
{
for (size_t idx = 0; idx < ArrayLength(kColors); ++idx) {

View File

@ -8,7 +8,6 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t, uint32_t
#include "gfxCore.h" // for NS_GFX_
#include "nscore.h" // for nsAString
class nsAString;
@ -53,37 +52,37 @@ typedef uint32_t nscolor;
// Translate a hex string to a color. Return true if it parses ok,
// otherwise return false.
// 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
// 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,
// otherwise return false.
// 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
// the hex-string syntax does not support transparency.
// Translate a color name to a color. Return true if it parses ok,
// 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
// *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
// 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
// name for it, returns null. If there are multiple possible color
// names for the given color, the first one in nsColorNameList.h
// (which is generally the first one in alphabetical order) will be
// returned.
NS_GFX_(const char*) NS_RGBToColorName(nscolor aColor);
const char* NS_RGBToColorName(nscolor aColor);
#endif /* nsColor_h___ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
--- a/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);
}
}

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 kFractionMask = ((1 << kFractionBits) - 1);
+NS_GFX_(YUVType) TypeFromSize(int ywidth,
+ int yheight,
+ int cbcrwidth,
+ int cbcrheight)
+YUVType TypeFromSize(int ywidth,
+ int yheight,
+ int cbcrwidth,
+ int cbcrheight)
+{
+ if (ywidth == cbcrwidth && yheight == cbcrheight) {
+ 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.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
void ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
--- a/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.
};
+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.
// Pass in YV16/YV12 depending on source format
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
int pic_x,
int pic_y,
void ConvertYCbCrToRGB32(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
int pic_x,
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,
- width);
- }
+NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int pic_x,
+ int pic_y,
+ int pic_width,
+ int pic_height,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch,
+ YUVType yuv_type) {
+void ConvertYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int pic_x,
+ int pic_y,
+ int pic_width,
+ int pic_height,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch,
+ YUVType yuv_type) {
+ unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
+ unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
+ // 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,
- Rotate view_rotate,
- ScaleFilter filter) {
+NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int source_width,
+ int source_height,
+ int width,
+ int height,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch,
+ YUVType yuv_type,
+ Rotate view_rotate,
+ ScaleFilter filter) {
+void ScaleYCbCrToRGB32(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int source_width,
+ int source_height,
+ int width,
+ int height,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch,
+ YUVType yuv_type,
+ Rotate view_rotate,
+ ScaleFilter filter) {
+ bool has_mmx = supports_mmx();
+
// 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 rgbstride,
- YUVType yuv_type);
+NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane,
+ const uint8* vplane,
+ uint8* rgbframe,
+ int pic_x,
+ int pic_y,
+ int pic_width,
+ int pic_height,
+ int ystride,
+ int uvstride,
+ int rgbstride,
+ YUVType yuv_type);
+void ConvertYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane,
+ const uint8* vplane,
+ uint8* rgbframe,
+ int pic_x,
+ int pic_y,
+ int pic_width,
+ int pic_height,
+ int ystride,
+ int uvstride,
+ int rgbstride,
+ YUVType yuv_type);
// Scale a frame of YUV to 32 bit ARGB.
// Supports rotation and mirroring.
@ -501,20 +501,20 @@ diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
-
-} // namespace media
-
+NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane,
+ const uint8* vplane,
+ uint8* rgbframe,
+ int source_width,
+ int source_height,
+ int width,
+ int height,
+ int ystride,
+ int uvstride,
+ int rgbstride,
+ YUVType yuv_type,
+ Rotate view_rotate,
+ ScaleFilter filter);
+void ScaleYCbCrToRGB32(const uint8* yplane,
+ const uint8* uplane,
+ const uint8* vplane,
+ uint8* rgbframe,
+ int source_width,
+ int source_height,
+ int width,
+ int height,
+ int ystride,
+ int uvstride,
+ int rgbstride,
+ YUVType yuv_type,
+ Rotate view_rotate,
+ ScaleFilter filter);
+
+} // namespace gfx
+} // 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 *v_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_width,
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* v_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_width,
int pic_height,

View File

@ -17,7 +17,7 @@ namespace gfx {
#ifdef HAVE_YCBCR_TO_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* vplane,
uint8* rgbframe,
@ -31,14 +31,14 @@ NS_GFX_(void) ConvertYCbCrToRGB565(const uint8* yplane,
YUVType yuv_type);
// 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_width,
int pic_height,
YUVType yuv_type);
// 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 *vplane,
uint8_t *rgbframe,
@ -55,7 +55,7 @@ NS_GFX_(void) ScaleYCbCrToRGB565(const uint8_t *yplane,
ScaleFilter filter);
// 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_width,
int source_height,

View File

@ -31,7 +31,7 @@ const int kFractionBits = 16;
const int kFractionMax = 1 << kFractionBits;
const int kFractionMask = ((1 << kFractionBits) - 1);
NS_GFX_(YUVType) TypeFromSize(int ywidth,
YUVType TypeFromSize(int ywidth,
int yheight,
int cbcrwidth,
int cbcrheight)
@ -48,18 +48,18 @@ NS_GFX_(YUVType) TypeFromSize(int ywidth,
}
// Convert a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
int pic_height,
int y_pitch,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type) {
void ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
int pic_height,
int y_pitch,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type) {
unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
// 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.
NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int source_width,
int source_height,
int width,
int height,
int y_pitch,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type,
Rotate view_rotate,
ScaleFilter filter) {
void ScaleYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int source_width,
int source_height,
int width,
int height,
int y_pitch,
int uv_pitch,
int rgb_pitch,
YUVType yuv_type,
Rotate view_rotate,
ScaleFilter filter) {
bool has_mmx = supports_mmx();
// 4096 allows 3 buffers to fit in 12k.

View File

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

View File

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

View File

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

View File

@ -70,14 +70,21 @@ public:
* decode.
* @param aHasAlpha Whether or not this frame has an alpha channel.
* 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,
uint8_t* aOutputBuffer,
bool aHasAlpha);
bool aHasAlpha,
bool aFlipVertically = false);
/// Retrieves the buffer into which the Decoder should write each row.
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.
void CommitRow();
@ -117,7 +124,8 @@ private:
int32_t mCurrentOutLine;
int32_t mCurrentInLine;
bool mHasAlpha;
bool mHasAlpha : 1;
bool mFlipVertically : 1;
};
#else
@ -139,12 +147,13 @@ public:
const nsIntSize& TargetSize() const { return nsIntSize(); }
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;
}
uint8_t* RowBuffer() { return nullptr; }
void ClearRow(uint32_t = 0);
void CommitRow() { }
bool HasInvalidation() const { return false; }
DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }

View File

@ -36,7 +36,10 @@ static bool
ShouldDownscaleDuringDecode(const nsCString& aMimeType)
{
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

View File

@ -19,6 +19,8 @@
#include "RasterImage.h"
#include <algorithm>
using namespace mozilla::gfx;
namespace mozilla {
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
void
nsBMPDecoder::SetUseAlphaData(bool useAlphaData)
@ -122,15 +138,6 @@ nsBMPDecoder::GetCompressedImageSize() const
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
nsBMPDecoder::FinishInternal()
{
@ -147,7 +154,7 @@ nsBMPDecoder::FinishInternal()
nsIntRect r(0, 0, mBIH.width, GetHeight());
PostInvalidation(r);
if (mUseAlphaData) {
if (mUseAlphaData && mHaveAlphaData) {
PostFrameStop(Opacity::SOME_TRANSPARENCY);
} else {
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
// also if they use RLE encoding, because the 'delta' mode can skip pixels
// and cause implicit transparency.
if ((mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4) ||
(mBIH.bpp == 32 && mUseAlphaData)) {
bool hasTransparency = (mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4) ||
(mBIH.bpp == 32 && mUseAlphaData);
if (hasTransparency) {
PostHasTransparency();
}
@ -453,18 +461,25 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
}
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)) {
return;
}
MOZ_ASSERT(mImageData, "Should have a buffer now");
// Prepare for transparency
if ((mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4)) {
// Clear the image, as the RLE may jump over areas
memset(mImageData, 0, mImageDataLength);
if (mDownscaler) {
// BMPs store their rows in reverse order, so the downscaler needs to
// reverse them again when writing its output.
rv = mDownscaler->BeginFrame(GetSize(), mImageData, hasTransparency,
/* aFlipVertically = */ true);
if (NS_FAILED(rv)) {
return;
}
}
}
@ -606,8 +621,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
if (rowSize == mRowBytes) {
// Collected a whole row into mRow, process it
uint8_t* p = mRow;
uint32_t* d = reinterpret_cast<uint32_t*>(mImageData) +
PIXEL_OFFSET(mCurLine, 0);
uint32_t* d = mDownscaler
? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, 0);
uint32_t lpos = mBIH.width;
switch (mBIH.bpp) {
case 1:
@ -664,28 +681,11 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case 32:
while (lpos > 0) {
if (mUseAlphaData) {
if (!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));
if (MOZ_UNLIKELY(!mHaveAlphaData && p[3])) {
PostHasTransparency();
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 {
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,"
" but earlier check didn't catch it");
}
if (mDownscaler) {
mDownscaler->CommitRow();
}
mCurLine --;
if (mCurLine == 0) { // Finished last line
break;
@ -741,8 +746,12 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
uint32_t pixelsNeeded = std::min<uint32_t>(mBIH.width - mCurPos,
mStateData);
if (pixelsNeeded) {
uint32_t* d = reinterpret_cast<uint32_t*>
(mImageData) + PIXEL_OFFSET(mCurLine, mCurPos);
uint32_t* d = mDownscaler
? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
+ mCurPos
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, mCurPos);
mCurPos += pixelsNeeded;
if (mBIH.compression == BMPINFOHEADER::RLE8) {
do {
@ -761,6 +770,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
switch(byte) {
case RLE::ESCAPE_EOL:
// End of Line: Go to next row
if (mDownscaler) {
mDownscaler->CommitRow();
}
mCurLine --;
mCurPos = 0;
mState = eRLEStateInitial;
@ -810,11 +823,20 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// Handle the XDelta and proceed to get Y Delta
byte = *aBuffer++;
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;
// Delta encoding makes it possible to skip pixels
// making the image transparent.
if (MOZ_UNLIKELY(!mHaveAlphaData)) {
PostHasTransparency();
mHaveAlphaData = true;
}
mUseAlphaData = mHaveAlphaData = true;
if (mCurPos > mBIH.width) {
@ -824,7 +846,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mState = eRLEStateNeedYDelta;
continue;
case eRLEStateNeedYDelta:
case eRLEStateNeedYDelta: {
// Get the Y Delta and then "handle" the move
byte = *aBuffer++;
aCount--;
@ -833,10 +855,26 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// making the image transparent.
if (MOZ_UNLIKELY(!mHaveAlphaData)) {
PostHasTransparency();
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;
}
case eRLEStateAbsoluteMode: // Absolute Mode
case eRLEStateAbsoluteModePadded:
@ -845,9 +883,12 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// represents the number of pixels
// that follow, each of which contains
// the color index of a single pixel.
uint32_t* d = reinterpret_cast<uint32_t*>
(mImageData) +
PIXEL_OFFSET(mCurLine, mCurPos);
uint32_t* d = mDownscaler
? reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer())
+ mCurPos
: reinterpret_cast<uint32_t*>(mImageData)
+ PIXEL_OFFSET(mCurLine, mCurPos);
uint32_t* oldPos = d;
if (mBIH.compression == BMPINFOHEADER::RLE8) {
while (aCount > 0 && mStateData > 0) {
@ -903,9 +944,15 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
const uint32_t rows = mOldLine - mCurLine;
if (rows) {
// Invalidate
nsIntRect r(0, mBIH.height < 0 ? -mBIH.height - mOldLine : mCurLine,
mBIH.width, rows);
PostInvalidation(r);
if (!mDownscaler) {
nsIntRect r(0, mBIH.height < 0 ? -mBIH.height - mOldLine : mCurLine,
mBIH.width, rows);
PostInvalidation(r);
} else if (mDownscaler->HasInvalidation()) {
DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
PostInvalidation(invalidRect.mOriginalSizeRect,
Some(invalidRect.mTargetSizeRect));
}
mOldLine = mCurLine;
}

View File

@ -9,6 +9,7 @@
#include "BMPFileHeaders.h"
#include "Decoder.h"
#include "Downscaler.h"
#include "gfxColor.h"
#include "nsAutoPtr.h"
@ -24,6 +25,8 @@ class nsBMPDecoder : public Decoder
public:
~nsBMPDecoder();
nsresult SetTargetSize(const nsIntSize& aSize) override;
// 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
// 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
// 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,
uint32_t aCount) override;
@ -71,6 +77,8 @@ private:
char mRawBuf[BIH_INTERNAL_LENGTH::WIN_V3]; //< If this is changed,
// WriteInternal() MUST be updated
Maybe<Downscaler> mDownscaler;
uint32_t mLOH; //< Length of the header
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
// 'AND buffer mask' which appears after the bitmap resource.
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
// 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
// The alpha mask should be checked in all other cases.
if (static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
GetBitsPerPixel() != 32 ||
!static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
HasAlphaData()) {
if (bmpDecoder->GetBitsPerPixel() != 32 || !bmpDecoder->HasAlphaData()) {
uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
if (mPos == bmpDataEnd) {
mPos++;
@ -573,9 +573,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mCurLine--;
mRowBytes = 0;
uint32_t* imageData =
static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
GetImageData();
uint32_t* imageData = bmpDecoder->GetImageData();
if (!imageData) {
PostDataError();
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
// pixel was transparent.
if (sawTransparency) {
PostHasTransparency();
PostHasTransparency();
bmpDecoder->SetHasAlphaData();
}
}
}

View File

@ -12,15 +12,20 @@
#include "RasterImage.h"
#include <algorithm>
using namespace mozilla::gfx;
using std::min;
namespace mozilla {
namespace image {
nsIconDecoder::nsIconDecoder(RasterImage* aImage)
: Decoder(aImage),
mWidth(-1),
mHeight(-1),
mPixBytesRead(0),
mState(iconStateStart)
: Decoder(aImage)
, mExpectedDataLength(0)
, mPixBytesRead(0)
, mState(iconStateStart)
, mWidth(-1)
, mHeight(-1)
{
// Nothing to do
}
@ -28,15 +33,25 @@ nsIconDecoder::nsIconDecoder(RasterImage* aImage)
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
nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
{
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
while (aCount > 0) {
switch (mState) {
@ -73,9 +88,16 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
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?");
nsresult rv = AllocateBasicFrame();
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
: GetSize();
nsresult rv = AllocateFrame(0, targetSize,
IntRect(IntPoint(), targetSize),
gfx::SurfaceFormat::B8G8R8A8);
if (NS_FAILED(rv)) {
mState = iconStateFinished;
return;
@ -84,6 +106,16 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
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
aBuffer++;
aCount--;
@ -93,25 +125,60 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case iconStateReadPixels: {
// How many bytes are we reading?
bytesToRead = std::min(aCount, mImageDataLength - mPixBytesRead);
uint32_t bytesToRead = min(aCount, mExpectedDataLength - mPixBytesRead);
// Copy the bytes
memcpy(mImageData + mPixBytesRead, aBuffer, bytesToRead);
if (mDownscaler) {
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
// always the full icon
nsIntRect r(0, 0, mWidth, mHeight);
// Update global state; we're about to read |bytesToRead| bytes.
aCount -= bytesToRead;
mPixBytesRead += bytesToRead;
// Invalidate
PostInvalidation(r);
if (rowOffset > 0) {
// Finish the current row.
const uint32_t remaining = bytesPerRow - rowOffset;
memcpy(row + rowOffset, aBuffer, remaining);
aBuffer += remaining;
bytesToRead -= remaining;
mDownscaler->CommitRow();
}
// Book Keeping
aBuffer += bytesToRead;
aCount -= bytesToRead;
mPixBytesRead += bytesToRead;
// Copy the bytes a row at a time.
while (bytesToRead > bytesPerRow) {
memcpy(row, aBuffer, bytesPerRow);
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 (mPixBytesRead == mImageDataLength) {
if (mPixBytesRead == mExpectedDataLength) {
PostFrameStop();
PostDecodeDone();
mState = iconStateFinished;

View File

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

View File

@ -1314,6 +1314,7 @@ if test "$GNU_CXX"; then
# -Wparentheses - catches `if (a=b)` and operator precedence bugs
# -Wpointer-arith - catches pointer arithmetic using NULL or sizeof(void)
# -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
# -Wreturn-type - catches missing returns, zero false positives
# -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=, 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)
fi

View File

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

View File

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

View File

@ -371,6 +371,11 @@ CommonAnimationManager::FlushAnimations()
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);
}
}
@ -883,10 +888,6 @@ AnimationCollection::RequestRestyle(RestyleType aRestyleType)
return;
}
MOZ_ASSERT(mElement->GetCrossShadowCurrentDoc() == presContext->Document(),
"Element::UnbindFromTree should have destroyed the element "
"transition/animations object");
// Steps for Restyle::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 1164813-1.html
load 1167782-1.html
load 1200568-1.html
load large_border_image_width.html
load border-image-visited-link.html

View File

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

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