mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Merge m-c to fx-team a=merge
This commit is contained in:
commit
df5afea581
6
CLOBBER
6
CLOBBER
@ -22,8 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
<<<<<<< local
|
||||
Bug 1092813 needs a CLOBBER
|
||||
=======
|
||||
Bug 1056337 - Change the default compiler on B2G ICS to gcc 4.8.
|
||||
>>>>>>> other
|
||||
Bug 1087560 changed a mochitest manifest without touching its moz.build.
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "6bf7a21e0dbf766076bfd1c15e59dea7f25a4c13",
|
||||
"revision": "1d065718099172104bee68bc190b583a0472a5e3",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="28be739bcdcbc9eb91c0bdbff1f7d3eab717969b"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="73eeaa23172c26e732972c318ea6aab20e0e1cae"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7c9e7cabbde941b976e0e40a3a1d94e21aa9c5e9"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -65,5 +65,5 @@ MOZ_JSDOWNLOADS=1
|
||||
|
||||
MOZ_BUNDLED_FONTS=1
|
||||
|
||||
JSGC_GENERATIONAL=1
|
||||
JS_GC_SMALL_CHUNK_SIZE=1
|
||||
export JSGC_GENERATIONAL=1
|
||||
export JS_GC_SMALL_CHUNK_SIZE=1
|
||||
|
@ -63,4 +63,4 @@ MOZ_ACTIVITIES=1
|
||||
MOZ_JSDOWNLOADS=1
|
||||
MOZ_WEBM_ENCODER=1
|
||||
# Enable generational GC on desktop.
|
||||
JSGC_GENERATIONAL=1
|
||||
export JSGC_GENERATIONAL=1
|
||||
|
@ -197,6 +197,9 @@ chmod +x $CONFIG_STATUS
|
||||
|
||||
define([MOZ_RUN_CONFIG_STATUS],
|
||||
[
|
||||
|
||||
MOZ_RUN_ALL_SUBCONFIGURES()
|
||||
|
||||
rm -fr confdefs* $ac_clean_files
|
||||
dnl Execute config.status, unless --no-create was passed to configure.
|
||||
if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
|
||||
|
@ -16,6 +16,7 @@ define([AC_INIT_PREPARE],
|
||||
[_MOZ_AC_INIT_PREPARE($1)
|
||||
MOZ_CONFIG_LOG_TRAP
|
||||
> subconfigures
|
||||
> skip_subconfigures
|
||||
])
|
||||
|
||||
define([AC_OUTPUT_SUBDIRS],
|
||||
@ -53,17 +54,34 @@ define([AC_OUTPUT_SUBDIRS],
|
||||
|
||||
eval $dumpenv $PYTHON $_topsrcdir/build/subconfigure.py --prepare "$srcdir" "$moz_config_dir" "$_CONFIG_SHELL" $ac_configure_args ifelse($2,,,--cache-file="$2")
|
||||
|
||||
dnl Execute subconfigure, unless --no-recursion was passed to configure.
|
||||
if test "$no_recursion" != yes; then
|
||||
trap '' EXIT
|
||||
if ! $PYTHON $_topsrcdir/build/subconfigure.py "$objdir"; then
|
||||
exit 1
|
||||
fi
|
||||
MOZ_CONFIG_LOG_TRAP
|
||||
fi
|
||||
dnl Actual subconfigure execution happens in MOZ_RUN_CONFIG_STATUS
|
||||
done
|
||||
])
|
||||
|
||||
define([AC_OUTPUT_SUBDIRS_NOW],
|
||||
[
|
||||
for moz_config_dir_ in $1; do
|
||||
AC_OUTPUT_SUBDIRS($moz_config_dir_,$2)
|
||||
tail -1 subconfigures >> skip_subconfigures
|
||||
MOZ_RUN_SUBCONFIGURES(`tail -1 skip_subconfigures`)
|
||||
done
|
||||
])
|
||||
|
||||
define([MOZ_RUN_SUBCONFIGURES],
|
||||
[dnl Execute subconfigure, unless --no-recursion was passed to configure.
|
||||
if test "$no_recursion" != yes; then
|
||||
trap '' EXIT
|
||||
if ! $PYTHON $_topsrcdir/build/subconfigure.py $1; then
|
||||
exit 1
|
||||
fi
|
||||
MOZ_CONFIG_LOG_TRAP
|
||||
fi
|
||||
])
|
||||
|
||||
define([MOZ_RUN_ALL_SUBCONFIGURES],
|
||||
MOZ_RUN_SUBCONFIGURES([--list subconfigures --skip skip_subconfigures])
|
||||
)
|
||||
|
||||
dnl Print error messages in config.log as well as stderr
|
||||
define([AC_MSG_ERROR],
|
||||
[{ echo "configure: error: $1" 1>&2; echo "configure: error: $1" 1>&5; exit 1; }])
|
||||
|
@ -180,7 +180,7 @@ if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
|
||||
export LDFLAGS="$HOST_LDFLAGS"
|
||||
ac_configure_args="$HOST_ICU_BUILD_OPTS"
|
||||
ac_configure_args="$ac_configure_args --enable-static --disable-shared --enable-extras=no --enable-icuio=no --enable-layout=no --enable-tests=no --enable-samples=no"
|
||||
AC_OUTPUT_SUBDIRS(intl/icu/source:intl/icu/host)
|
||||
AC_OUTPUT_SUBDIRS_NOW(intl/icu/source:intl/icu/host)
|
||||
) || exit 1
|
||||
# generate config/icucross.mk
|
||||
$GMAKE -C $_objdir/intl/icu/host/ config/icucross.mk
|
||||
|
@ -15,6 +15,28 @@ import pickle
|
||||
|
||||
import mozpack.path as mozpath
|
||||
|
||||
try:
|
||||
from multiprocessing import Pool, cpu_count
|
||||
except ImportError:
|
||||
import itertools
|
||||
|
||||
class Pool(object):
|
||||
def __init__(self, size):
|
||||
pass
|
||||
|
||||
def imap_unordered(self, fn, iterable):
|
||||
return itertools.imap(fn, iterable)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
def join(self):
|
||||
pass
|
||||
|
||||
def cpu_count():
|
||||
return 1
|
||||
|
||||
|
||||
class File(object):
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
@ -70,6 +92,9 @@ PRECIOUS_VARS = set([
|
||||
])
|
||||
|
||||
|
||||
CONFIGURE_DATA = 'configure.pkl'
|
||||
|
||||
|
||||
# Autoconf, in some of the sub-configures used in the tree, likes to error
|
||||
# out when "precious" variables change in value. The solution it gives to
|
||||
# straighten things is to either run make distclean or remove config.cache.
|
||||
@ -160,7 +185,7 @@ def get_config_files(data):
|
||||
return config_files, command_files
|
||||
|
||||
|
||||
def prepare(data_file, srcdir, objdir, shell, args):
|
||||
def prepare(srcdir, objdir, shell, args):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--target', type=str)
|
||||
parser.add_argument('--host', type=str)
|
||||
@ -172,7 +197,7 @@ def prepare(data_file, srcdir, objdir, shell, args):
|
||||
# will take it from the configure path anyways).
|
||||
parser.add_argument('--srcdir', type=str)
|
||||
|
||||
data_file = os.path.join(objdir, data_file)
|
||||
data_file = os.path.join(objdir, CONFIGURE_DATA)
|
||||
previous_args = None
|
||||
if os.path.exists(data_file):
|
||||
with open(data_file, 'rb') as f:
|
||||
@ -227,10 +252,15 @@ def prepare(data_file, srcdir, objdir, shell, args):
|
||||
pickle.dump(data, f)
|
||||
|
||||
|
||||
def run(data_file, objdir):
|
||||
ret = 0
|
||||
def prefix_lines(text, prefix):
|
||||
return ''.join('%s> %s' % (prefix, line) for line in text.splitlines(True))
|
||||
|
||||
with open(os.path.join(objdir, data_file), 'rb') as f:
|
||||
|
||||
def run(objdir):
|
||||
ret = 0
|
||||
output = ''
|
||||
|
||||
with open(os.path.join(objdir, CONFIGURE_DATA), 'rb') as f:
|
||||
data = pickle.load(f)
|
||||
|
||||
data['objdir'] = objdir
|
||||
@ -271,6 +301,8 @@ def run(data_file, objdir):
|
||||
cleared_cache:
|
||||
skip_configure = False
|
||||
|
||||
relobjdir = os.path.relpath(objdir, os.getcwd())
|
||||
|
||||
if not skip_configure:
|
||||
command = [data['shell'], configure]
|
||||
for kind in ('target', 'build', 'host'):
|
||||
@ -283,13 +315,14 @@ def run(data_file, objdir):
|
||||
# We're going to run it ourselves.
|
||||
command += ['--no-create']
|
||||
|
||||
print 'configuring in %s' % os.path.relpath(objdir, os.getcwd())
|
||||
print 'running %s' % ' '.join(command[:-1])
|
||||
print prefix_lines('configuring', relobjdir)
|
||||
print prefix_lines('running %s' % ' '.join(command[:-1]), relobjdir)
|
||||
sys.stdout.flush()
|
||||
ret = subprocess.call(command, cwd=objdir, env=data['env'])
|
||||
|
||||
if ret:
|
||||
return ret
|
||||
try:
|
||||
output += subprocess.check_output(command,
|
||||
stderr=subprocess.STDOUT, cwd=objdir, env=data['env'])
|
||||
except subprocess.CalledProcessError as e:
|
||||
return relobjdir, e.returncode, e.output
|
||||
|
||||
# Leave config.status with a new timestamp if configure is newer than
|
||||
# its original mtime.
|
||||
@ -317,25 +350,61 @@ def run(data_file, objdir):
|
||||
|
||||
if not skip_config_status:
|
||||
if skip_configure:
|
||||
print 'running config.status in %s' % os.path.relpath(objdir,
|
||||
os.getcwd())
|
||||
print prefix_lines('running config.status', relobjdir)
|
||||
sys.stdout.flush()
|
||||
ret = subprocess.call([data['shell'], '-c', './config.status'],
|
||||
cwd=objdir, env=data['env'])
|
||||
try:
|
||||
output += subprocess.check_output([data['shell'], '-c',
|
||||
'./config.status'], stderr=subprocess.STDOUT, cwd=objdir,
|
||||
env=data['env'])
|
||||
except subprocess.CalledProcessError as e:
|
||||
ret = e.returncode
|
||||
output += e.output
|
||||
|
||||
for f in contents:
|
||||
f.update_time()
|
||||
|
||||
return relobjdir, ret, output
|
||||
|
||||
|
||||
def subconfigure(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--list', type=str,
|
||||
help='File containing a list of subconfigures to run')
|
||||
parser.add_argument('--skip', type=str,
|
||||
help='File containing a list of Subconfigures to skip')
|
||||
parser.add_argument('subconfigures', type=str, nargs='*',
|
||||
help='Subconfigures to run if no list file is given')
|
||||
args, others = parser.parse_known_args(args)
|
||||
subconfigures = args.subconfigures
|
||||
if args.list:
|
||||
subconfigures.extend(open(args.list, 'rb').read().splitlines())
|
||||
if args.skip:
|
||||
skips = set(open(args.skip, 'rb').read().splitlines())
|
||||
subconfigures = [s for s in subconfigures if s not in skips]
|
||||
|
||||
if not subconfigures:
|
||||
return 0
|
||||
|
||||
ret = 0
|
||||
# One would think using a ThreadPool would be faster, considering
|
||||
# everything happens in subprocesses anyways, but no, it's actually
|
||||
# slower on Windows. (20s difference overall!)
|
||||
pool = Pool(min(len(subconfigures), cpu_count()))
|
||||
for relobjdir, returncode, output in \
|
||||
pool.imap_unordered(run, subconfigures):
|
||||
print prefix_lines(output, relobjdir)
|
||||
sys.stdout.flush()
|
||||
ret = max(returncode, ret)
|
||||
if ret:
|
||||
break
|
||||
pool.close()
|
||||
pool.join()
|
||||
return ret
|
||||
|
||||
|
||||
CONFIGURE_DATA = 'configure.pkl'
|
||||
|
||||
def main(args):
|
||||
if args[0] != '--prepare':
|
||||
if len(args) != 1:
|
||||
raise Exception('Usage: %s relativeobjdir' % __file__)
|
||||
return run(CONFIGURE_DATA, args[0])
|
||||
return subconfigure(args)
|
||||
|
||||
topsrcdir = os.path.abspath(args[1])
|
||||
subdir = args[2]
|
||||
@ -347,7 +416,7 @@ def main(args):
|
||||
srcdir = os.path.join(topsrcdir, srcdir)
|
||||
objdir = os.path.abspath(subdir)
|
||||
|
||||
return prepare(CONFIGURE_DATA, srcdir, objdir, args[3], args[4:])
|
||||
return prepare(srcdir, objdir, args[3], args[4:])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -245,13 +245,6 @@ endif
|
||||
#
|
||||
_ENABLE_PIC=1
|
||||
|
||||
# PGO on MSVC is opt-in
|
||||
ifdef _MSC_VER
|
||||
ifndef MSVC_ENABLE_PGO
|
||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# No sense in profiling tools
|
||||
ifdef INTERNAL_TOOLS
|
||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||
@ -289,10 +282,6 @@ endif
|
||||
endif # MOZ_PROFILE_USE
|
||||
endif # NO_PROFILE_GUIDED_OPTIMIZE
|
||||
|
||||
ifdef _MSC_VER
|
||||
OS_LDFLAGS += $(DELAYLOAD_LDFLAGS)
|
||||
endif # _MSC_VER
|
||||
|
||||
MAKE_JARS_FLAGS = \
|
||||
-t $(topsrcdir) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
@ -702,24 +691,6 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
|
||||
# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
|
||||
# arguments syntax. Should only be used for system libraries
|
||||
|
||||
# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
|
||||
# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
|
||||
|
||||
# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
|
||||
# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
|
||||
|
||||
ifdef GNU_CC
|
||||
EXPAND_LIBNAME = $(addprefix -l,$(1))
|
||||
else
|
||||
EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
endif
|
||||
EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
|
||||
|
||||
PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply
|
||||
|
||||
export CL_INCLUDES_PREFIX
|
||||
|
@ -479,12 +479,6 @@ ifeq ($(OS_ARCH),GNU)
|
||||
OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef USE_DELAYIMP
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,delayimp)
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# MINGW32
|
||||
#
|
||||
|
94
configure.in
94
configure.in
@ -71,7 +71,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.20
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.8.6
|
||||
SQLITE_VERSION=3.8.7.1
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
@ -3958,7 +3958,6 @@ NSS_NO_LIBPKIX=
|
||||
MOZ_CONTENT_SANDBOX=
|
||||
MOZ_GMP_SANDBOX=
|
||||
MOZ_SANDBOX=1
|
||||
JSGC_GENERATIONAL=
|
||||
|
||||
case "$target_os" in
|
||||
mingw*)
|
||||
@ -7048,6 +7047,31 @@ elif test -z "$_ENABLE_LOGREFCNT"; then
|
||||
AC_DEFINE(NO_BUILD_REFCNT_LOGGING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl moz_aproximate_location
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(approximate_location,
|
||||
[ --enable-approximate-location Enable approximate location ],
|
||||
MOZ_APPROX_LOCATION=1,
|
||||
MOZ_APPROX_LOCATION= )
|
||||
if test -n "$MOZ_APPROX_LOCATION"; then
|
||||
AC_DEFINE(MOZ_APPROX_LOCATION)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl moz_gps_debug
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(gps_debug,
|
||||
[ --enable-gps-debug Enable gps specific debug messages ],
|
||||
MOZ_GPS_DEBUG=1,
|
||||
MOZ_GPS_DEBUG= )
|
||||
if test -n "$MOZ_GPS_DEBUG"; then
|
||||
AC_DEFINE(MOZ_GPS_DEBUG)
|
||||
fi
|
||||
if test -n "$MOZ_DEBUG"; then
|
||||
AC_DEFINE(MOZ_GPS_DEBUG)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl moz_dump_painting
|
||||
dnl ========================================================
|
||||
@ -7323,61 +7347,6 @@ if test -n "$JS_CRASH_DIAGNOSTICS"; then
|
||||
AC_DEFINE(JS_CRASH_DIAGNOSTICS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use incremental GC
|
||||
dnl ========================================================
|
||||
JSGC_INCREMENTAL=1
|
||||
MOZ_ARG_DISABLE_BOOL(gcincremental,
|
||||
[ --disable-gcincremental Disable incremental GC],
|
||||
JSGC_INCREMENTAL= )
|
||||
if test -n "$JSGC_INCREMENTAL"; then
|
||||
AC_DEFINE(JSGC_INCREMENTAL)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use generational GC
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(gcgenerational,
|
||||
[ --disable-gcgenerational Disable generational GC],
|
||||
JSGC_GENERATIONAL= ,
|
||||
JSGC_GENERATIONAL=1 )
|
||||
if test -n "$JSGC_GENERATIONAL"; then
|
||||
AC_DEFINE(JSGC_GENERATIONAL)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use compacting GC
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(gccompacting,
|
||||
[ --enable-gccompacting Compact the JS heap by moving GC things],
|
||||
JS_GCCOMPACTING=1,
|
||||
JS_GCCOMPACTING= )
|
||||
if test -n "$JS_GCCOMPACTING"; then
|
||||
AC_DEFINE(JS_GCCOMPACTING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use a smaller chunk size for GC chunks
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(small-chunk-size,
|
||||
[ --enable-small-chunk-size Allocate memory for JS GC things in smaller chunks],
|
||||
JS_GC_SMALL_CHUNK_SIZE=1,
|
||||
JS_GC_SMALL_CHUNK_SIZE= )
|
||||
if test -n "$JS_GC_SMALL_CHUNK_SIZE"; then
|
||||
AC_DEFINE(JS_GC_SMALL_CHUNK_SIZE)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Zealous JavaScript GC
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(gczeal,
|
||||
[ --enable-gczeal Enable zealous JavaScript GCing],
|
||||
JS_GC_ZEAL=1,
|
||||
JS_GC_ZEAL= )
|
||||
if test -n "$JS_GC_ZEAL" -o -n "$MOZ_DEBUG"; then
|
||||
AC_DEFINE(JS_GC_ZEAL)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable static checking using gcc-dehydra
|
||||
dnl ========================================================
|
||||
@ -9265,7 +9234,7 @@ if test -n "$_subconfigure_subdir"; then
|
||||
srcdir="$srcdir/.."
|
||||
_save_ac_configure_args="$ac_configure_args"
|
||||
ac_configure_args="$_subconfigure_config_args"
|
||||
AC_OUTPUT_SUBDIRS("$_subconfigure_subdir",$cache_file)
|
||||
AC_OUTPUT_SUBDIRS_NOW("$_subconfigure_subdir",$cache_file)
|
||||
ac_configure_args="$_save_ac_configure_args"
|
||||
srcdir="$_save_srcdir"
|
||||
fi
|
||||
@ -9317,15 +9286,6 @@ if test -z "$JS_SHARED_LIBRARY" ; then
|
||||
ac_configure_args="$ac_configure_args --disable-export-js"
|
||||
fi
|
||||
fi
|
||||
if test -z "$JSGC_GENERATIONAL" ; then
|
||||
ac_configure_args="$ac_configure_args --disable-gcgenerational"
|
||||
fi
|
||||
if test -n "$JS_GCCOMPACTING" ; then
|
||||
ac_configure_args="$ac_configure_args --enable-gccompacting"
|
||||
fi
|
||||
if test -n "$JS_GC_SMALL_CHUNK_SIZE" ; then
|
||||
ac_configure_args="$ac_configure_args --enable-small-chunk-size"
|
||||
fi
|
||||
if test -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
|
||||
ac_configure_args="$ac_configure_args --with-nspr-cflags='$NSPR_CFLAGS'"
|
||||
ac_configure_args="$ac_configure_args --with-nspr-libs='$NSPR_LIBS'"
|
||||
|
@ -1,9 +1,6 @@
|
||||
This is sqlite 3.8.6.1
|
||||
This is SQLite 3.8.7.1
|
||||
|
||||
NB: We did not update SQLITE_VERSION in configure.in for this. See bug 1088143
|
||||
for the rationale.
|
||||
|
||||
-- Kyle Huey <khuey@kylehuey.com>, 10/23/2014
|
||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 11/2014
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.8.6.1"
|
||||
#define SQLITE_VERSION_NUMBER 3008006
|
||||
#define SQLITE_SOURCE_ID "2014-10-22 14:22:11 1581c30c389acb2af2c7040d3583c89d48f9bea5"
|
||||
#define SQLITE_VERSION "3.8.7.1"
|
||||
#define SQLITE_VERSION_NUMBER 3008007
|
||||
#define SQLITE_SOURCE_ID "2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -497,6 +497,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
|
||||
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
|
||||
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
||||
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@ -2099,7 +2100,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
||||
** turns off all busy handlers.
|
||||
**
|
||||
** ^(There can only be a single busy handler for a particular
|
||||
** [database connection] any any given moment. If another busy handler
|
||||
** [database connection] at any given moment. If another busy handler
|
||||
** was defined (using [sqlite3_busy_handler()]) prior to calling
|
||||
** this routine, that other busy handler is cleared.)^
|
||||
**
|
||||
@ -2303,6 +2304,10 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
||||
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
|
||||
** a NULL pointer.
|
||||
**
|
||||
** ^The sqlite3_malloc64(N) routine works just like
|
||||
** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead
|
||||
** of a signed 32-bit integer.
|
||||
**
|
||||
** ^Calling sqlite3_free() with a pointer previously returned
|
||||
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
|
||||
** that it might be reused. ^The sqlite3_free() routine is
|
||||
@ -2314,24 +2319,38 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
||||
** might result if sqlite3_free() is called with a non-NULL pointer that
|
||||
** was not obtained from sqlite3_malloc() or sqlite3_realloc().
|
||||
**
|
||||
** ^(The sqlite3_realloc() interface attempts to resize a
|
||||
** prior memory allocation to be at least N bytes, where N is the
|
||||
** second parameter. The memory allocation to be resized is the first
|
||||
** parameter.)^ ^ If the first parameter to sqlite3_realloc()
|
||||
** ^The sqlite3_realloc(X,N) interface attempts to resize a
|
||||
** prior memory allocation X to be at least N bytes.
|
||||
** ^If the X parameter to sqlite3_realloc(X,N)
|
||||
** is a NULL pointer then its behavior is identical to calling
|
||||
** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
|
||||
** ^If the second parameter to sqlite3_realloc() is zero or
|
||||
** sqlite3_malloc(N).
|
||||
** ^If the N parameter to sqlite3_realloc(X,N) is zero or
|
||||
** negative then the behavior is exactly the same as calling
|
||||
** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
|
||||
** ^sqlite3_realloc() returns a pointer to a memory allocation
|
||||
** of at least N bytes in size or NULL if sufficient memory is unavailable.
|
||||
** sqlite3_free(X).
|
||||
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
|
||||
** of at least N bytes in size or NULL if insufficient memory is available.
|
||||
** ^If M is the size of the prior allocation, then min(N,M) bytes
|
||||
** of the prior allocation are copied into the beginning of buffer returned
|
||||
** by sqlite3_realloc() and the prior allocation is freed.
|
||||
** ^If sqlite3_realloc() returns NULL, then the prior allocation
|
||||
** is not freed.
|
||||
** by sqlite3_realloc(X,N) and the prior allocation is freed.
|
||||
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
|
||||
** prior allocation is not freed.
|
||||
**
|
||||
** ^The memory returned by sqlite3_malloc() and sqlite3_realloc()
|
||||
** ^The sqlite3_realloc64(X,N) interfaces works the same as
|
||||
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
|
||||
** of a 32-bit signed integer.
|
||||
**
|
||||
** ^If X is a memory allocation previously obtained from sqlite3_malloc(),
|
||||
** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then
|
||||
** sqlite3_msize(X) returns the size of that memory allocation in bytes.
|
||||
** ^The value returned by sqlite3_msize(X) might be larger than the number
|
||||
** of bytes requested when X was allocated. ^If X is a NULL pointer then
|
||||
** sqlite3_msize(X) returns zero. If X points to something that is not
|
||||
** the beginning of memory allocation, or if it points to a formerly
|
||||
** valid memory allocation that has now been freed, then the behavior
|
||||
** of sqlite3_msize(X) is undefined and possibly harmful.
|
||||
**
|
||||
** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
|
||||
** sqlite3_malloc64(), and sqlite3_realloc64()
|
||||
** is always aligned to at least an 8 byte boundary, or to a
|
||||
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
|
||||
** option is used.
|
||||
@ -2359,8 +2378,11 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
||||
** [sqlite3_free()] or [sqlite3_realloc()].
|
||||
*/
|
||||
SQLITE_API void *sqlite3_malloc(int);
|
||||
SQLITE_API void *sqlite3_malloc64(sqlite3_uint64);
|
||||
SQLITE_API void *sqlite3_realloc(void*, int);
|
||||
SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64);
|
||||
SQLITE_API void sqlite3_free(void*);
|
||||
SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Memory Allocator Statistics
|
||||
@ -2647,9 +2669,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** an English language description of the error following a failure of any
|
||||
** of the sqlite3_open() routines.
|
||||
**
|
||||
** ^The default encoding for the database will be UTF-8 if
|
||||
** sqlite3_open() or sqlite3_open_v2() is called and
|
||||
** UTF-16 in the native byte order if sqlite3_open16() is used.
|
||||
** ^The default encoding will be UTF-8 for databases created using
|
||||
** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases
|
||||
** created using sqlite3_open16() will be UTF-16 in the native byte order.
|
||||
**
|
||||
** Whether or not an error occurs when it is opened, resources
|
||||
** associated with the [database connection] handle should be released by
|
||||
@ -2737,13 +2759,14 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** then it is interpreted as an absolute path. ^If the path does not begin
|
||||
** with a '/' (meaning that the authority section is omitted from the URI)
|
||||
** then the path is interpreted as a relative path.
|
||||
** ^On windows, the first component of an absolute path
|
||||
** is a drive specification (e.g. "C:").
|
||||
** ^(On windows, the first component of an absolute path
|
||||
** is a drive specification (e.g. "C:").)^
|
||||
**
|
||||
** [[core URI query parameters]]
|
||||
** The query component of a URI may contain parameters that are interpreted
|
||||
** either by SQLite itself, or by a [VFS | custom VFS implementation].
|
||||
** SQLite interprets the following three query parameters:
|
||||
** SQLite and its built-in [VFSes] interpret the
|
||||
** following query parameters:
|
||||
**
|
||||
** <ul>
|
||||
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
|
||||
@ -2778,11 +2801,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** a URI filename, its value overrides any behavior requested by setting
|
||||
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
||||
**
|
||||
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
|
||||
** "1") or "false" (or "off" or "no" or "0") to indicate that the
|
||||
** <li> <b>psow</b>: ^The psow parameter indicates whether or not the
|
||||
** [powersafe overwrite] property does or does not apply to the
|
||||
** storage media on which the database file resides. ^The psow query
|
||||
** parameter only works for the built-in unix and Windows VFSes.
|
||||
** storage media on which the database file resides.
|
||||
**
|
||||
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
|
||||
** which if set disables file locking in rollback journal modes. This
|
||||
@ -3078,6 +3099,10 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
**
|
||||
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
||||
** <dd>The maximum depth of recursion for triggers.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
|
||||
** <dd>The maximum number of auxiliary worker threads that a single
|
||||
** [prepared statement] may start.</dd>)^
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_LIMIT_LENGTH 0
|
||||
@ -3091,6 +3116,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
|
||||
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
|
||||
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
||||
#define SQLITE_LIMIT_WORKER_THREADS 11
|
||||
|
||||
/*
|
||||
** CAPI3REF: Compiling An SQL Statement
|
||||
@ -3364,18 +3390,18 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** If the fourth parameter to sqlite3_bind_blob() is negative, then
|
||||
** the behavior is undefined.
|
||||
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
|
||||
** or sqlite3_bind_text16() then that parameter must be the byte offset
|
||||
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
|
||||
** that parameter must be the byte offset
|
||||
** where the NUL terminator would occur assuming the string were NUL
|
||||
** terminated. If any NUL characters occur at byte offsets less than
|
||||
** the value of the fourth parameter then the resulting string value will
|
||||
** contain embedded NULs. The result of expressions involving strings
|
||||
** with embedded NULs is undefined.
|
||||
**
|
||||
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
|
||||
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
|
||||
** ^The fifth argument to the BLOB and string binding interfaces
|
||||
** is a destructor used to dispose of the BLOB or
|
||||
** string after SQLite has finished with it. ^The destructor is called
|
||||
** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
|
||||
** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
|
||||
** to dispose of the BLOB or string even if the call to bind API fails.
|
||||
** ^If the fifth argument is
|
||||
** the special value [SQLITE_STATIC], then SQLite assumes that the
|
||||
** information is in static, unmanaged space and does not need to be freed.
|
||||
@ -3383,6 +3409,14 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** SQLite makes its own private copy of the data immediately, before
|
||||
** the sqlite3_bind_*() routine returns.
|
||||
**
|
||||
** ^The sixth argument to sqlite3_bind_text64() must be one of
|
||||
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
|
||||
** to specify the encoding of the text in the third parameter. If
|
||||
** the sixth argument to sqlite3_bind_text64() is not one of the
|
||||
** allowed values shown above, or if the text encoding is different
|
||||
** from the encoding specified by the sixth parameter, then the behavior
|
||||
** is undefined.
|
||||
**
|
||||
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
|
||||
** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
|
||||
** (just an integer to hold its size) while it is being processed.
|
||||
@ -3403,6 +3437,9 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
**
|
||||
** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
|
||||
** [error code] if anything goes wrong.
|
||||
** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB
|
||||
** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or
|
||||
** [SQLITE_MAX_LENGTH].
|
||||
** ^[SQLITE_RANGE] is returned if the parameter
|
||||
** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
|
||||
**
|
||||
@ -3410,12 +3447,16 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
|
||||
*/
|
||||
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
|
||||
SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
|
||||
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
|
||||
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
|
||||
SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
|
||||
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
|
||||
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
||||
SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
|
||||
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
|
||||
void(*)(void*), unsigned char encoding);
|
||||
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
||||
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
||||
|
||||
@ -4164,7 +4205,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** object results in undefined behavior.
|
||||
**
|
||||
** ^These routines work just like the corresponding [column access functions]
|
||||
** except that these routines take a single [protected sqlite3_value] object
|
||||
** except that these routines take a single [protected sqlite3_value] object
|
||||
** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
|
||||
**
|
||||
** ^The sqlite3_value_text16() interface extracts a UTF-16 string
|
||||
@ -4411,6 +4452,10 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** set the return value of the application-defined function to be
|
||||
** a text string which is represented as UTF-8, UTF-16 native byte order,
|
||||
** UTF-16 little endian, or UTF-16 big endian, respectively.
|
||||
** ^The sqlite3_result_text64() interface sets the return value of an
|
||||
** application-defined function to be a text string in an encoding
|
||||
** specified by the fifth (and last) parameter, which must be one
|
||||
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
|
||||
** ^SQLite takes the text result from the application from
|
||||
** the 2nd parameter of the sqlite3_result_text* interfaces.
|
||||
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
|
||||
@ -4454,6 +4499,7 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** the [sqlite3_context] pointer, the results are undefined.
|
||||
*/
|
||||
SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
|
||||
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
|
||||
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
|
||||
@ -4464,6 +4510,8 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
|
||||
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
|
||||
SQLITE_API void sqlite3_result_null(sqlite3_context*);
|
||||
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char encoding);
|
||||
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
@ -6160,12 +6208,13 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
|
||||
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
|
||||
#define SQLITE_TESTCTRL_BYTEORDER 22
|
||||
#define SQLITE_TESTCTRL_ISINIT 23
|
||||
#define SQLITE_TESTCTRL_LAST 23
|
||||
#define SQLITE_TESTCTRL_SORTER_MMAP 24
|
||||
#define SQLITE_TESTCTRL_LAST 24
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
@ -6356,12 +6405,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
|
||||
** the current value is always zero.)^
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** <dd>This parameter returns the approximate number of bytes of heap
|
||||
** memory used by all pager caches associated with the database connection.)^
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** <dd>This parameter returns the approximate number of bytes of heap
|
||||
** memory used to store the schema for all databases associated
|
||||
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
|
||||
** ^The full amount of memory used by the schemas is reported, even if the
|
||||
@ -6370,7 +6419,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** <dd>This parameter returns the approximate number of bytes of heap
|
||||
** and lookaside memory used by all prepared statements associated with
|
||||
** the database connection.)^
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
|
||||
|
@ -61,18 +61,21 @@ AlarmsManager.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
// Run JSON.stringify() in the sand box with the principal of the calling
|
||||
// web page to ensure no cross-origin object is involved. A "Permission
|
||||
// Denied" error will be thrown in case of privilege violation.
|
||||
let sandbox = new Cu.Sandbox(Cu.getWebIDLCallerPrincipal());
|
||||
sandbox.data = aData;
|
||||
let data = Cu.evalInSandbox("JSON.stringify(data)", sandbox);
|
||||
let data = aData;
|
||||
if (aData) {
|
||||
// Run JSON.stringify() in the sand box with the principal of the calling
|
||||
// web page to ensure no cross-origin object is involved. A "Permission
|
||||
// Denied" error will be thrown in case of privilege violation.
|
||||
let sandbox = new Cu.Sandbox(Cu.getWebIDLCallerPrincipal());
|
||||
sandbox.data = aData;
|
||||
data = JSON.parse(Cu.evalInSandbox("JSON.stringify(data)", sandbox));
|
||||
}
|
||||
let request = this.createRequest();
|
||||
this._cpmm.sendAsyncMessage("AlarmsManager:Add",
|
||||
{ requestId: this.getRequestId(request),
|
||||
date: aDate,
|
||||
ignoreTimezone: isIgnoreTimezone,
|
||||
data: JSON.parse(data),
|
||||
data: data,
|
||||
pageURL: this._pageURL,
|
||||
manifestURL: this._manifestURL });
|
||||
return request;
|
||||
|
@ -18,3 +18,5 @@ skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') #Bug
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug1037079.html]
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug1090896.html]
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
|
83
dom/alarm/test/test_bug1090896.html
Normal file
83
dom/alarm/test/test_bug1090896.html
Normal file
@ -0,0 +1,83 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test time alert is fired for Bug 1090896</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
function testFireTimeAlertWithNoData() {
|
||||
var secondsLater = new Date();
|
||||
secondsLater.setSeconds(secondsLater.getSeconds() + 1);
|
||||
|
||||
var domRequest;
|
||||
try {
|
||||
// Set system message handler.
|
||||
navigator.mozSetMessageHandler('alarm', function(message){
|
||||
ok(true, "Time alert has been fired.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
domRequest = navigator.mozAlarms.add(secondsLater, "honorTimezone");
|
||||
} catch (e) {
|
||||
ok(false, "Unexpected exception trying to set time alert. " + e);
|
||||
|
||||
return SimpleTest.finish();
|
||||
}
|
||||
domRequest.onsuccess = function(e) {
|
||||
ok(true, "Set time alert. Waiting to be fired.");
|
||||
};
|
||||
domRequest.onerror = function(e) {
|
||||
ok(false, "Unable to set time alert.");
|
||||
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["dom.mozAlarms.enabled", true]]
|
||||
}, function() {
|
||||
var isAllowedToTest = true;
|
||||
|
||||
if (navigator.appVersion.indexOf("Android") !== -1) {
|
||||
ok(true, "mozAlarms is not allowed on Android for now. " +
|
||||
"TODO Bug 863557.");
|
||||
isAllowedToTest = false;
|
||||
} else if (SpecialPowers.wrap(document).nodePrincipal.appStatus ==
|
||||
SpecialPowers.Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED) {
|
||||
ok(true, "mozAlarms is not allowed for non-installed apps. " +
|
||||
"TODO Bug 876981.");
|
||||
isAllowedToTest = false;
|
||||
}
|
||||
|
||||
if (isAllowedToTest) {
|
||||
ok(true, "Start to test...");
|
||||
testFireTimeAlertWithNoData();
|
||||
} else {
|
||||
// A sanity check to make sure we must run tests on Firefox OS (B2G).
|
||||
if (navigator.userAgent.indexOf("Mobile") != -1 &&
|
||||
navigator.appVersion.indexOf("Android") == -1) {
|
||||
ok(false, "Should run the test on Firefox OS (B2G)!");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPermissions([{'type': 'alarms', 'allow': true, 'context': document}], startTests);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -451,6 +451,8 @@ this.DOMApplicationRegistry = {
|
||||
if (supportUseCurrentProfile()) {
|
||||
this._readManifests([{ id: aId }]).then((aResult) => {
|
||||
let data = aResult[0];
|
||||
this.webapps[aId].kind = this.webapps[aId].kind ||
|
||||
this.appKind(this.webapps[aId], aResult[0].manifest);
|
||||
PermissionsInstaller.installPermissions({
|
||||
manifest: data.manifest,
|
||||
manifestURL: this.webapps[aId].manifestURL,
|
||||
|
@ -492,7 +492,10 @@ public:
|
||||
mWriteParams(aWriteParams),
|
||||
mNeedAllowNextSynchronizedOp(false),
|
||||
mPersistence(quota::PERSISTENCE_TYPE_INVALID),
|
||||
mState(eInitial)
|
||||
mState(eInitial),
|
||||
mIsApp(false),
|
||||
mHasUnlimStoragePerm(false),
|
||||
mEnforcingQuota(true)
|
||||
{
|
||||
MOZ_ASSERT(IsMainProcess());
|
||||
}
|
||||
@ -593,6 +596,9 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
InitPersistenceType();
|
||||
|
||||
nsresult
|
||||
InitOnMainThread();
|
||||
|
||||
@ -659,8 +665,58 @@ private:
|
||||
eFinished, // Terminal state
|
||||
};
|
||||
State mState;
|
||||
|
||||
bool mIsApp;
|
||||
bool mHasUnlimStoragePerm;
|
||||
bool mEnforcingQuota;
|
||||
};
|
||||
|
||||
void
|
||||
MainProcessRunnable::InitPersistenceType()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == eInitial);
|
||||
|
||||
if (mOpenMode == eOpenForWrite) {
|
||||
MOZ_ASSERT(mPersistence == quota::PERSISTENCE_TYPE_INVALID);
|
||||
|
||||
// If we are performing install-time caching of an app, we'd like to store
|
||||
// the cache entry in persistent storage so the entry is never evicted,
|
||||
// but we need to check that quota is not enforced for the app.
|
||||
// That justifies us in skipping all quota checks when storing the cache
|
||||
// entry and avoids all the issues around the persistent quota prompt.
|
||||
// If quota is enforced for the app, then we can still cache in temporary
|
||||
// for a likely good first-run experience.
|
||||
|
||||
MOZ_ASSERT_IF(mWriteParams.mInstalled, mIsApp);
|
||||
|
||||
if (mWriteParams.mInstalled &&
|
||||
!QuotaManager::IsQuotaEnforced(quota::PERSISTENCE_TYPE_PERSISTENT,
|
||||
mOrigin, mIsApp, mHasUnlimStoragePerm)) {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_PERSISTENT;
|
||||
} else {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// For the reasons described above, apps may have cache entries in both
|
||||
// persistent and temporary storage. At lookup time we don't know how and
|
||||
// where the given script was cached, so start the search in persistent
|
||||
// storage and, if that fails, search in temporary storage. (Non-apps can
|
||||
// only be stored in temporary storage.)
|
||||
|
||||
MOZ_ASSERT_IF(mPersistence != quota::PERSISTENCE_TYPE_INVALID,
|
||||
mIsApp && mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT);
|
||||
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_INVALID && mIsApp) {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_PERSISTENT;
|
||||
} else {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
MainProcessRunnable::InitOnMainThread()
|
||||
{
|
||||
@ -670,58 +726,30 @@ MainProcessRunnable::InitOnMainThread()
|
||||
QuotaManager* qm = QuotaManager::GetOrCreate();
|
||||
NS_ENSURE_STATE(qm);
|
||||
|
||||
nsresult rv = QuotaManager::GetInfoFromPrincipal(mPrincipal, &mGroup,
|
||||
&mOrigin, nullptr, nullptr);
|
||||
nsresult rv =
|
||||
QuotaManager::GetInfoFromPrincipal(mPrincipal,
|
||||
quota::PERSISTENCE_TYPE_INVALID,
|
||||
&mGroup, &mOrigin, &mIsApp,
|
||||
&mHasUnlimStoragePerm);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isApp = mPrincipal->GetAppStatus() !=
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
// XXX Don't use mGroup yet! We might need to update it right after we
|
||||
// initialize persistence type.
|
||||
|
||||
if (mOpenMode == eOpenForWrite) {
|
||||
MOZ_ASSERT(mPersistence == quota::PERSISTENCE_TYPE_INVALID);
|
||||
if (mWriteParams.mInstalled) {
|
||||
// If we are performing install-time caching of an app, we'd like to store
|
||||
// the cache entry in persistent storage so the entry is never evicted,
|
||||
// but we need to verify that the app has unlimited storage permissions
|
||||
// first. Unlimited storage permissions justify us in skipping all quota
|
||||
// checks when storing the cache entry and avoids all the issues around
|
||||
// the persistent quota prompt.
|
||||
MOZ_ASSERT(isApp);
|
||||
InitPersistenceType();
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> pm =
|
||||
services::GetPermissionManager();
|
||||
NS_ENSURE_TRUE(pm, NS_ERROR_UNEXPECTED);
|
||||
|
||||
uint32_t permission;
|
||||
rv = pm->TestPermissionFromPrincipal(mPrincipal,
|
||||
PERMISSION_STORAGE_UNLIMITED,
|
||||
&permission);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// If app doens't have the unlimited storage permission, we can still
|
||||
// cache in temporary for a likely good first-run experience.
|
||||
mPersistence = permission == nsIPermissionManager::ALLOW_ACTION
|
||||
? quota::PERSISTENCE_TYPE_PERSISTENT
|
||||
: quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
} else {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
} else {
|
||||
// For the reasons described above, apps may have cache entries in both
|
||||
// persistent and temporary storage. At lookup time we don't know how and
|
||||
// where the given script was cached, so start the search in persistent
|
||||
// storage and, if that fails, search in temporary storage. (Non-apps can
|
||||
// only be stored in temporary storage.)
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_INVALID) {
|
||||
mPersistence = isApp ? quota::PERSISTENCE_TYPE_PERSISTENT
|
||||
: quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
} else {
|
||||
MOZ_ASSERT(isApp);
|
||||
MOZ_ASSERT(mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT);
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
// XXX Since we couldn't pass persistence type to GetInfoFromPrincipal(),
|
||||
// we need to do this manually.
|
||||
// This hack is only temporary, it will go away once we have regular
|
||||
// metadata files for persistent storge.
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT) {
|
||||
mGroup = mOrigin;
|
||||
}
|
||||
|
||||
mEnforcingQuota =
|
||||
QuotaManager::IsQuotaEnforced(mPersistence, mOrigin, mIsApp,
|
||||
mHasUnlimStoragePerm);
|
||||
|
||||
QuotaManager::GetStorageId(mPersistence, mOrigin, quota::Client::ASMJS,
|
||||
NS_LITERAL_STRING("asmjs"), mStorageId);
|
||||
|
||||
@ -737,13 +765,10 @@ MainProcessRunnable::ReadMetadata()
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
// Only track quota for temporary storage. For persistent storage, we've
|
||||
// already checked that we have unlimited-storage permissions.
|
||||
bool trackQuota = mPersistence == quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
|
||||
nsresult rv = qm->EnsureOriginIsInitialized(mPersistence, mGroup, mOrigin,
|
||||
trackQuota,
|
||||
getter_AddRefs(mDirectory));
|
||||
nsresult rv =
|
||||
qm->EnsureOriginIsInitialized(mPersistence, mGroup, mOrigin, mIsApp,
|
||||
mHasUnlimStoragePerm,
|
||||
getter_AddRefs(mDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDirectory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
|
||||
@ -811,11 +836,7 @@ MainProcessRunnable::OpenCacheFileForWrite()
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
// If we are allocating in temporary storage, ask the QuotaManager if we're
|
||||
// within the quota. If we are allocating in persistent storage, we've already
|
||||
// checked that we have the unlimited-storage permission, so there is nothing
|
||||
// to check.
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (mEnforcingQuota) {
|
||||
// Create the QuotaObject before all file IO and keep it alive until caching
|
||||
// completes to get maximum assertion coverage in QuotaManager against
|
||||
// concurrent removal, etc.
|
||||
@ -866,7 +887,7 @@ MainProcessRunnable::OpenCacheFileForRead()
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (mEnforcingQuota) {
|
||||
// Even though it's not strictly necessary, create the QuotaObject before
|
||||
// all file IO and keep it alive until caching completes to get maximum
|
||||
// assertion coverage in QuotaManager against concurrent removal, etc.
|
||||
|
@ -1546,7 +1546,7 @@ private:
|
||||
return data->mConstructorCID != nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
static bool IsConstructable(const nsGlobalNameStruct *aNameStruct)
|
||||
{
|
||||
|
@ -3094,13 +3094,6 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsCString origin;
|
||||
quota::PersistenceType defaultPersistenceType;
|
||||
nsresult rv =
|
||||
quota::QuotaManager::GetInfoFromWindow(window, nullptr, &origin, nullptr,
|
||||
&defaultPersistenceType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
IDBOpenDBOptions options;
|
||||
JS::Rooted<JS::Value> optionsVal(aCx, aOptions);
|
||||
if (!options.Init(aCx, optionsVal)) {
|
||||
@ -3108,7 +3101,13 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
|
||||
}
|
||||
|
||||
quota::PersistenceType persistenceType =
|
||||
quota::PersistenceTypeFromStorage(options.mStorage, defaultPersistenceType);
|
||||
quota::PersistenceTypeFromStorage(options.mStorage);
|
||||
|
||||
nsCString origin;
|
||||
nsresult rv =
|
||||
quota::QuotaManager::GetInfoFromWindow(window, persistenceType, nullptr,
|
||||
&origin, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
|
||||
indexedDB::IndexedDatabaseManager::Get();
|
||||
|
@ -12401,7 +12401,7 @@ nsIDocument::CreateNSResolver(nsINode& aNodeResolver)
|
||||
|
||||
already_AddRefed<XPathResult>
|
||||
nsIDocument::Evaluate(JSContext* aCx, const nsAString& aExpression,
|
||||
nsINode* aContextNode, XPathNSResolver* aResolver,
|
||||
nsINode& aContextNode, XPathNSResolver* aResolver,
|
||||
uint16_t aType, JS::Handle<JSObject*> aResult,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
|
@ -160,6 +160,7 @@ GK_ATOM(browser, "browser")
|
||||
GK_ATOM(mozbrowser, "mozbrowser")
|
||||
GK_ATOM(bulletinboard, "bulletinboard")
|
||||
GK_ATOM(button, "button")
|
||||
GK_ATOM(brighttitlebarforeground, "brighttitlebarforeground")
|
||||
GK_ATOM(callTemplate, "call-template")
|
||||
GK_ATOM(cancel, "cancel")
|
||||
GK_ATOM(canvas, "canvas")
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "WindowNamedPropertiesHandler.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsISelectionListener.h"
|
||||
#include "nsCaret.h"
|
||||
|
||||
// Helper Classes
|
||||
#include "nsJSUtils.h"
|
||||
@ -9332,6 +9333,38 @@ CheckReason(int16_t aReason, SelectionChangeReason aReasonType)
|
||||
}
|
||||
}
|
||||
|
||||
static nsRect
|
||||
GetSelectionBoundingRect(Selection* aSel, nsIPresShell* aShell)
|
||||
{
|
||||
nsRect res;
|
||||
// Bounding client rect may be empty after calling GetBoundingClientRect
|
||||
// when range is collapsed. So we get caret's rect when range is
|
||||
// collapsed.
|
||||
if (aSel->IsCollapsed()) {
|
||||
aShell->FlushPendingNotifications(Flush_Layout);
|
||||
nsIFrame* frame = nsCaret::GetGeometry(aSel, &res);
|
||||
if (frame) {
|
||||
nsIFrame* relativeTo =
|
||||
nsLayoutUtils::GetContainingBlockForClientRect(frame);
|
||||
res = nsLayoutUtils::TransformFrameRectToAncestor(frame, res, relativeTo);
|
||||
}
|
||||
} else {
|
||||
int32_t rangeCount = aSel->GetRangeCount();
|
||||
nsLayoutUtils::RectAccumulator accumulator;
|
||||
for (int32_t idx = 0; idx < rangeCount; ++idx) {
|
||||
nsRange* range = aSel->GetRangeAt(idx);
|
||||
nsRange::CollectClientRects(&accumulator, range,
|
||||
range->GetStartParent(), range->StartOffset(),
|
||||
range->GetEndParent(), range->EndOffset(),
|
||||
true, false);
|
||||
}
|
||||
res = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect :
|
||||
accumulator.mResultRect;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
|
||||
{
|
||||
@ -9377,17 +9410,7 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, in
|
||||
}
|
||||
|
||||
Selection* selection = static_cast<Selection*>(aSel);
|
||||
int32_t rangeCount = selection->GetRangeCount();
|
||||
nsLayoutUtils::RectAccumulator accumulator;
|
||||
for (int32_t idx = 0; idx < rangeCount; ++idx) {
|
||||
nsRange* range = selection->GetRangeAt(idx);
|
||||
nsRange::CollectClientRects(&accumulator, range,
|
||||
range->GetStartParent(), range->StartOffset(),
|
||||
range->GetEndParent(), range->EndOffset(),
|
||||
true, false);
|
||||
}
|
||||
nsRect rect = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect :
|
||||
accumulator.mResultRect;
|
||||
nsRect rect = GetSelectionBoundingRect(selection, mDoc->GetShell());
|
||||
nsRefPtr<DOMRect> domRect = new DOMRect(ToSupports(this));
|
||||
domRect->SetLayoutRect(rect);
|
||||
init.mBoundingClientRect = domRect;
|
||||
|
@ -136,8 +136,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x6bbf1955, 0xd9c4, 0x4d61, \
|
||||
{ 0xbf, 0x75, 0x1b, 0xba, 0x55, 0xf7, 0x99, 0xc2 } }
|
||||
{ 0x1f343423, 0x957c, 0x4da3, \
|
||||
{ 0xaa, 0xa3, 0x07, 0x37, 0x54, 0x3e, 0x79, 0x2a } }
|
||||
|
||||
// Enum for requesting a particular type of document when creating a doc
|
||||
enum DocumentFlavor {
|
||||
@ -2344,7 +2344,7 @@ public:
|
||||
mozilla::ErrorResult& rv);
|
||||
nsINode* CreateNSResolver(nsINode& aNodeResolver);
|
||||
already_AddRefed<mozilla::dom::XPathResult>
|
||||
Evaluate(JSContext* aCx, const nsAString& aExpression, nsINode* aContextNode,
|
||||
Evaluate(JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode,
|
||||
mozilla::dom::XPathNSResolver* aResolver, uint16_t aType,
|
||||
JS::Handle<JSObject*> aResult, mozilla::ErrorResult& rv);
|
||||
// Touch event handlers already on nsINode
|
||||
|
@ -375,7 +375,9 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug337631.html]
|
||||
[test_bug338541.xhtml]
|
||||
[test_bug338583.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(https not working, bug 907770) b2g-debug(https not working, bug 907770) b2g-desktop(43 total - bug 901343, specialpowers.wrap issue createsystemxhr)
|
||||
# b2g(https not working, bug 907770) b2g-debug(https not working, bug 907770) b2g-desktop(43 total - bug 901343, specialpowers.wrap issue createsystemxhr)
|
||||
# e10s - bug 970589, bug 1091934
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'linux' && debug && e10s)
|
||||
[test_bug338679.html]
|
||||
[test_bug339494.html]
|
||||
[test_bug339494.xhtml]
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -281,7 +282,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
SourceSurface*
|
||||
CanvasImageCache::Lookup(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize)
|
||||
gfx::IntSize* aSize)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
@ -297,7 +298,7 @@ CanvasImageCache::Lookup(Element* aImage,
|
||||
|
||||
gImageCache->MarkUsed(entry->mData);
|
||||
|
||||
*aSize = entry->mData->mSize;
|
||||
*aSize = gfx::ToIntSize(entry->mData->mSize);
|
||||
return entry->mData->mSourceSurface;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
*/
|
||||
static SourceSurface* Lookup(dom::Element* aImage,
|
||||
dom::HTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize);
|
||||
gfx::IntSize* aSize);
|
||||
|
||||
/**
|
||||
* This is the same as Lookup, except it works on any image recently drawn
|
||||
|
@ -3957,7 +3957,7 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
||||
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
||||
|
||||
RefPtr<SourceSurface> srcSurf;
|
||||
gfxIntSize imgSize;
|
||||
gfx::IntSize imgSize;
|
||||
|
||||
Element* element;
|
||||
|
||||
@ -4008,7 +4008,7 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
||||
return;
|
||||
}
|
||||
|
||||
imgSize = res.mSize;
|
||||
imgSize = gfx::ToIntSize(res.mSize);
|
||||
|
||||
// Scale sw/sh based on aspect ratio
|
||||
if (image.IsHTMLVideoElement()) {
|
||||
@ -4028,7 +4028,7 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
||||
if (res.mSourceSurface) {
|
||||
if (res.mImageRequest) {
|
||||
CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
|
||||
res.mSourceSurface, imgSize);
|
||||
res.mSourceSurface, ThebesIntSize(imgSize));
|
||||
}
|
||||
|
||||
srcSurf = res.mSourceSurface;
|
||||
@ -4113,7 +4113,7 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
|
||||
mgfx::Rect* bounds,
|
||||
mgfx::Rect dest,
|
||||
mgfx::Rect src,
|
||||
gfxIntSize imgSize)
|
||||
gfx::IntSize imgSize)
|
||||
{
|
||||
MOZ_ASSERT(src.width > 0 && src.height > 0,
|
||||
"Need positive source width and height");
|
||||
|
@ -726,7 +726,7 @@ protected:
|
||||
mozilla::gfx::Rect* bounds,
|
||||
mozilla::gfx::Rect dest,
|
||||
mozilla::gfx::Rect src,
|
||||
gfxIntSize imgSize);
|
||||
gfx::IntSize imgSize);
|
||||
|
||||
nsString& GetFont()
|
||||
{
|
||||
|
@ -1,14 +1,18 @@
|
||||
[DEFAULT]
|
||||
skip-if = ((os == 'linux') && (buildapp == 'b2g'))
|
||||
|
||||
support-files =
|
||||
webgl-mochitest/driver-info.js
|
||||
webgl-mochitest/webgl-util.js
|
||||
|
||||
[webgl-mochitest/test-backbuffer-channels.html]
|
||||
[webgl-mochitest/test-hidden-alpha.html]
|
||||
[webgl-mochitest/test_backbuffer_channels.html]
|
||||
fail-if = (os == 'b2g')
|
||||
[webgl-mochitest/test_depth_readpixels.html]
|
||||
[webgl-mochitest/test_draw.html]
|
||||
[webgl-mochitest/test_fb_param.html]
|
||||
[webgl-mochitest/test_fb_param_crash.html]
|
||||
[webgl-mochitest/test_hidden_alpha.html]
|
||||
fail-if = (os == 'b2g')
|
||||
[webgl-mochitest/test_highp_fs.html]
|
||||
[webgl-mochitest/test_no_arr_points.html]
|
||||
skip-if = android_version == '10' #Android 2.3 aws only; bug 1030942
|
||||
|
@ -48,6 +48,11 @@ function todo(val, text) {
|
||||
: 'Test <font color=\\'blue\\' >todo</font>: ';
|
||||
debug(status + text);
|
||||
}
|
||||
|
||||
SimpleTest = {
|
||||
waitForExplicitFinish: function() {},
|
||||
finish: function() {},
|
||||
};
|
||||
</script>
|
||||
<div id='mochi-to-testcase-output'></div>
|
||||
\n'''
|
||||
|
@ -8,7 +8,7 @@
|
||||
<script>
|
||||
|
||||
function TestAttribs(attribs) {
|
||||
debug('Testing attribs: ' + JSON.stringify(attribs));
|
||||
ok(true, 'Testing attribs: ' + JSON.stringify(attribs));
|
||||
var canvas = document.createElement('canvas');
|
||||
var gl = canvas.getContext('experimental-webgl', attribs);
|
||||
ok(gl, 'No tested attribs should result in failure to create a context');
|
@ -77,7 +77,7 @@ function Test(gl, prog) {
|
||||
|
||||
//////////////////
|
||||
|
||||
debug('clear(R,G,B,0)');
|
||||
ok(true, 'clear(R,G,B,0)');
|
||||
|
||||
Reset(gl);
|
||||
|
||||
@ -102,7 +102,7 @@ function Test(gl, prog) {
|
||||
|
||||
//////////////////
|
||||
|
||||
debug('mask(R,G,B,0), clear(R,G,B,1)');
|
||||
ok(true, 'mask(R,G,B,0), clear(R,G,B,1)');
|
||||
|
||||
Reset(gl);
|
||||
|
||||
@ -129,6 +129,7 @@ function Test(gl, prog) {
|
||||
'toDataURL should be unchanged after blending.');
|
||||
|
||||
ok(true, 'Test complete.');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
(function(){
|
||||
@ -146,6 +147,7 @@ function Test(gl, prog) {
|
||||
ok(prog, 'Program should link.');
|
||||
prog.aPosCoord = gl.getAttribLocation(prog, 'aPosCoord');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(function(){ Test(gl, prog); }, 500);
|
||||
})();
|
||||
|
@ -5,12 +5,15 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'nsGeolocationSettings.h',
|
||||
'nsGeoPosition.h',
|
||||
'nsGeoPositionIPCSerialiser.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsGeoGridFuzzer.cpp',
|
||||
'nsGeolocation.cpp',
|
||||
'nsGeolocationSettings.cpp',
|
||||
'nsGeoPosition.cpp',
|
||||
]
|
||||
|
||||
|
135
dom/geolocation/nsGeoGridFuzzer.cpp
Normal file
135
dom/geolocation/nsGeoGridFuzzer.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/* 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 <math.h>
|
||||
#include "nsGeoGridFuzzer.h"
|
||||
#include "nsGeoPosition.h"
|
||||
|
||||
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
|
||||
/* The following constants are taken from the World Geodetic System 1984 (WGS84)
|
||||
* reference model for the earth ellipsoid [1]. The values in the model are
|
||||
* an accepted standard for GPS and other navigational systems.
|
||||
*
|
||||
* [1] http://www.oosa.unvienna.org/pdf/icg/2012/template/WGS_84.pdf
|
||||
*/
|
||||
#define WGS84_a (6378137.0) // equitorial axis
|
||||
#define WGS84_b (6356752.314245179) // polar axis (a * (1-f))
|
||||
#define WGS84_f (1.0/298.257223563) // inverse flattening
|
||||
#define WGS84_EPSILON (5.72957795e-9) // 1e-10 radians in degrees
|
||||
#define sq(f) ((f) * (f))
|
||||
#define sign(f) (((f) < 0) ? -1 : 1)
|
||||
|
||||
/* if you have an ellipsoid with semi-major axis A and semi-minor axis B, the
|
||||
* radius at angle phi along the semi-major axis can be calculated with this
|
||||
* formula. by using the WGS84 values for A and B, we calculate the radius of
|
||||
* earth, given the angle of latitude, phi.*/
|
||||
#define LON_RADIUS(phi) (sqrt((sq(sq(WGS84_a) * cos(phi)) + sq(sq(WGS84_b) * sin(phi))) / \
|
||||
(sq(WGS84_a * cos(phi)) + sq(WGS84_b * sin(phi)))))
|
||||
/* the radius of earth changes as a function of latitude, to simplify I am
|
||||
* assuming the fixed radius of the earth halfway between the poles and the
|
||||
* equator. this is calculated from LON_RADIUS(M_PI/4), or the radius at
|
||||
* 45 degrees N.*/
|
||||
#define LAT_RADIUS (6367489.543863)
|
||||
|
||||
/* This function figures out the latitudinal grid square that the given
|
||||
* latitude coordinate falls into and then returns the latitudinal center of
|
||||
* that grid square. It handles the proper wrapping at the poles +/- 90
|
||||
* (e.g. +95 wraps to +85 and -95 wraps to -85) */
|
||||
static double GridAlgorithmLat(int32_t aDistMeters, double aLatDeg)
|
||||
{
|
||||
/* switch to radians */
|
||||
double phi = (aLatDeg * M_PI) / 180;
|
||||
|
||||
/* properly wrap the latitude */
|
||||
phi = atan(sin(phi) / fabs(cos(phi)));
|
||||
|
||||
/* calculate grid size in radians */
|
||||
double gridSizeRad = aDistMeters / LAT_RADIUS;
|
||||
|
||||
/* find the southern edge, in radians, of the grid cell, then add half of a
|
||||
* grid cell to find the center latitude in radians */
|
||||
double gridCenterPhi = gridSizeRad * floor(phi / gridSizeRad) + gridSizeRad / 2;
|
||||
|
||||
/* properly wrap it and return it in degrees */
|
||||
return atan(sin(gridCenterPhi) / fabs(cos(gridCenterPhi))) * (180.0 / M_PI);
|
||||
}
|
||||
|
||||
/* This function figures out the longitudinal grid square that the given longitude
|
||||
* coordinate falls into and then returns the longitudinal center of that grid
|
||||
* square. It handles the proper wrapping at +/- 180 (e.g. +185 wraps to -175
|
||||
* and -185 wraps to +175) */
|
||||
static double GridAlgorithmLon(int32_t aDistMeters, double aLatDeg, double aLonDeg)
|
||||
{
|
||||
/* switch to radians */
|
||||
double phi = (aLatDeg * M_PI) / 180;
|
||||
double theta = (aLonDeg * M_PI) / 180;
|
||||
|
||||
/* properly wrap the lat/lon */
|
||||
phi = atan(sin(phi) / fabs(cos(phi)));
|
||||
theta = atan2(sin(theta), cos(theta));
|
||||
|
||||
/* calculate grid size in radians */
|
||||
double gridSizeRad = aDistMeters / LON_RADIUS(phi);
|
||||
|
||||
/* find the western edge, in radians, of the grid cell, then add half of a
|
||||
* grid cell to find the center longitude in radians */
|
||||
double gridCenterTheta = gridSizeRad * floor(theta / gridSizeRad) + gridSizeRad / 2;
|
||||
|
||||
/* properly wrap it and return it in degrees */
|
||||
return atan2(sin(gridCenterTheta), cos(gridCenterTheta)) * (180.0 / M_PI);
|
||||
}
|
||||
|
||||
/* This function takes the grid size and the graticule coordinates of a
|
||||
* location and calculates which grid cell the coordinates fall within and
|
||||
* then returns the coordinates of the geographical center of the grid square.
|
||||
*/
|
||||
static void CalculateGridCoords(int32_t aDistKm, double& aLatDeg, double& aLonDeg)
|
||||
{
|
||||
// a grid size of 0 is the same as precise
|
||||
if (aDistKm == 0) {
|
||||
return;
|
||||
}
|
||||
aLonDeg = GridAlgorithmLon(aDistKm * 1000, aLatDeg, aLonDeg);
|
||||
aLatDeg = GridAlgorithmLat(aDistKm * 1000, aLatDeg);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMGeoPosition>
|
||||
nsGeoGridFuzzer::FuzzLocation(const GeolocationSetting & aSetting,
|
||||
nsIDOMGeoPosition * aPosition)
|
||||
{
|
||||
if (!aPosition) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
|
||||
nsresult rv = aPosition->GetCoords(getter_AddRefs(coords));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
if (!coords) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
double lat = 0.0, lon = 0.0;
|
||||
coords->GetLatitude(&lat);
|
||||
coords->GetLongitude(&lon);
|
||||
|
||||
// adjust lat/lon to be the center of the grid square
|
||||
CalculateGridCoords(aSetting.GetApproxDistance(), lat, lon);
|
||||
GPSLOG("approximate location with delta %d is %f, %f",
|
||||
aSetting.GetApproxDistance(), lat, lon);
|
||||
|
||||
// reusing the timestamp
|
||||
DOMTimeStamp ts;
|
||||
rv = aPosition->GetTimestamp(&ts);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
// return a position at sea level, N heading, 0 speed, 0 error.
|
||||
nsRefPtr<nsGeoPosition> pos = new nsGeoPosition(lat, lon, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, ts);
|
||||
return pos.forget();
|
||||
}
|
||||
|
||||
#endif
|
25
dom/geolocation/nsGeoGridFuzzer.h
Normal file
25
dom/geolocation/nsGeoGridFuzzer.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- 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 nsGeoGridFuzzer_h
|
||||
#define nsGeoGridFuzzer_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMGeoPosition.h"
|
||||
#include "nsGeolocationSettings.h"
|
||||
|
||||
class nsGeoGridFuzzer MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
|
||||
static already_AddRefed<nsIDOMGeoPosition>
|
||||
FuzzLocation(const GeolocationSetting& aSetting, nsIDOMGeoPosition* aPosition);
|
||||
|
||||
private:
|
||||
nsGeoGridFuzzer() {} // can't construct
|
||||
nsGeoGridFuzzer(const nsGeoGridFuzzer&) {} // can't copy
|
||||
};
|
||||
|
||||
#endif
|
@ -10,6 +10,8 @@
|
||||
#include "nsISettingsService.h"
|
||||
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsGeoGridFuzzer.h"
|
||||
#include "nsGeolocationSettings.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -26,6 +28,9 @@
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/SettingChangeNotificationBinding.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "prdtoa.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
#ifdef MOZ_ENABLE_QT5GEOPOSITION
|
||||
@ -48,8 +53,8 @@ class nsIPrincipal;
|
||||
// that a window can make.
|
||||
#define MAX_GEO_REQUESTS_PER_WINDOW 1500
|
||||
|
||||
// The settings key.
|
||||
#define GEO_SETINGS_ENABLED "geolocation.enabled"
|
||||
// the geolocation enabled setting
|
||||
#define GEO_SETTINGS_ENABLED "geolocation.enabled"
|
||||
|
||||
using mozilla::unused; // <snicker>
|
||||
using namespace mozilla;
|
||||
@ -76,7 +81,7 @@ class nsGeolocationRequest MOZ_FINAL
|
||||
int32_t aWatchId = 0);
|
||||
void Shutdown();
|
||||
|
||||
void SendLocation(nsIDOMGeoPosition* location);
|
||||
void SendLocation(nsIDOMGeoPosition* aLocation);
|
||||
bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
|
||||
void SetTimeoutTimer();
|
||||
void StopTimeoutTimer();
|
||||
@ -88,6 +93,8 @@ class nsGeolocationRequest MOZ_FINAL
|
||||
private:
|
||||
virtual ~nsGeolocationRequest();
|
||||
|
||||
already_AddRefed<nsIDOMGeoPosition> AdjustedLocation(nsIDOMGeoPosition*);
|
||||
|
||||
bool mIsWatchPositionRequest;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimeoutTimer;
|
||||
@ -130,22 +137,42 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// The geolocation is enabled by default:
|
||||
bool value = true;
|
||||
if (aResult.isBoolean()) {
|
||||
value = aResult.toBoolean();
|
||||
if (aName.EqualsASCII(GEO_SETTINGS_ENABLED)) {
|
||||
// The geolocation is enabled by default:
|
||||
bool value = true;
|
||||
if (aResult.isBoolean()) {
|
||||
value = aResult.toBoolean();
|
||||
}
|
||||
|
||||
GPSLOG("%s set to %s",
|
||||
NS_ConvertUTF16toUTF8(aName).get(),
|
||||
(value ? "ENABLED" : "DISABLED"));
|
||||
MozSettingValue(value);
|
||||
|
||||
} else {
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
if (gs) {
|
||||
gs->HandleGeolocationSettingsChange(aName, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
MozSettingValue(value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD HandleError(const nsAString& aName)
|
||||
{
|
||||
NS_WARNING("Unable to get value for '" GEO_SETINGS_ENABLED "'");
|
||||
if (aName.EqualsASCII(GEO_SETTINGS_ENABLED)) {
|
||||
GPSLOG("Unable to get value for '" GEO_SETTINGS_ENABLED "'");
|
||||
|
||||
// Default it's enabled:
|
||||
MozSettingValue(true);
|
||||
} else {
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
if (gs) {
|
||||
gs->HandleGeolocationSettingsError(aName);
|
||||
}
|
||||
}
|
||||
|
||||
// Default it's enabled:
|
||||
MozSettingValue(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -488,6 +515,65 @@ nsGeolocationRequest::StopTimeoutTimer()
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIDOMGeoPosition>
|
||||
SynthesizeLocation(DOMTimeStamp aTimestamp, double aLatitude, double aLongitude)
|
||||
{
|
||||
// return a position at sea level, N heading, 0 speed, 0 error.
|
||||
nsRefPtr<nsGeoPosition> pos = new nsGeoPosition(aLatitude, aLongitude,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
aTimestamp);
|
||||
return pos.forget();
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<nsIDOMGeoPosition>
|
||||
nsGeolocationRequest::AdjustedLocation(nsIDOMGeoPosition *aPosition)
|
||||
{
|
||||
nsCOMPtr<nsIDOMGeoPosition> pos = aPosition;
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
GPSLOG("child process just copying position");
|
||||
return pos.forget();
|
||||
}
|
||||
|
||||
// get the settings cache
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
if (!gs) {
|
||||
return pos.forget();
|
||||
}
|
||||
|
||||
// make sure ALA is enabled
|
||||
if (!gs->IsAlaEnabled()) {
|
||||
GPSLOG("ALA is disabled, returning precise location");
|
||||
return pos.forget();
|
||||
}
|
||||
|
||||
// look up the geolocation settings via the watch ID
|
||||
DOMTimeStamp ts(PR_Now() / PR_USEC_PER_MSEC);
|
||||
GeolocationSetting setting = gs->LookupGeolocationSetting(mWatchId);
|
||||
switch (setting.GetType()) {
|
||||
case GEO_ALA_TYPE_PRECISE:
|
||||
GPSLOG("returning precise location watch ID: %d", mWatchId);
|
||||
return pos.forget();
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
case GEO_ALA_TYPE_APPROX:
|
||||
GPSLOG("returning approximate location for watch ID: %d", mWatchId);
|
||||
return nsGeoGridFuzzer::FuzzLocation(setting, aPosition);
|
||||
#endif
|
||||
case GEO_ALA_TYPE_FIXED:
|
||||
GPSLOG("returning fixed location for watch ID:: %d", mWatchId);
|
||||
// use "now" as time stamp
|
||||
return SynthesizeLocation(ts, setting.GetFixedLatitude(),
|
||||
setting.GetFixedLongitude());
|
||||
case GEO_ALA_TYPE_NONE:
|
||||
GPSLOG("returning no location for watch ID: %d", mWatchId);
|
||||
// return nullptr so no location callback happens
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
|
||||
{
|
||||
@ -513,6 +599,12 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
|
||||
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
|
||||
aPosition->GetCoords(getter_AddRefs(coords));
|
||||
if (coords) {
|
||||
#ifdef MOZ_GPS_DEBUG
|
||||
double lat = 0.0, lon = 0.0;
|
||||
coords->GetLatitude(&lat);
|
||||
coords->GetLongitude(&lon);
|
||||
GPSLOG("returning coordinates: %f, %f", lat, lon);
|
||||
#endif
|
||||
wrapped = new Position(ToSupports(mLocator), aPosition);
|
||||
}
|
||||
}
|
||||
@ -559,7 +651,8 @@ nsGeolocationRequest::GetPrincipal()
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(aPosition, this);
|
||||
nsCOMPtr<nsIDOMGeoPosition> pos = AdjustedLocation(aPosition);
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(pos, this);
|
||||
NS_DispatchToMainThread(ev);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -646,8 +739,31 @@ nsresult nsGeolocationService::Init()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<GeolocationSettingsCallback> callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_SETINGS_ENABLED, callback);
|
||||
rv = settingsLock->Get(GEO_SETTINGS_ENABLED, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// look up the geolocation settings
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_ENABLED, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_TYPE, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_APPROX_DISTANCE, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_FIXED_COORDS, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_APP_SETTINGS, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
callback = new GeolocationSettingsCallback();
|
||||
rv = settingsLock->Get(GEO_ALA_ALWAYS_PRECISE, callback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
} else {
|
||||
// If we cannot obtain the settings service, we continue
|
||||
// assuming that the geolocation is enabled:
|
||||
@ -724,13 +840,17 @@ nsGeolocationService::HandleMozsettingChanged(nsISupports* aSubject)
|
||||
if (!WrappedJSToDictionary(cx, aSubject, setting)) {
|
||||
return;
|
||||
}
|
||||
if (!setting.mKey.EqualsASCII(GEO_SETINGS_ENABLED)) {
|
||||
if (!setting.mKey.EqualsASCII(GEO_SETTINGS_ENABLED)) {
|
||||
return;
|
||||
}
|
||||
if (!setting.mValue.isBoolean()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPSLOG("mozsetting changed: %s == %s",
|
||||
NS_ConvertUTF16toUTF8(setting.mKey).get(),
|
||||
(setting.mValue.toBoolean() ? "TRUE" : "FALSE"));
|
||||
|
||||
HandleMozsettingValue(setting.mValue.toBoolean());
|
||||
}
|
||||
|
||||
@ -1325,6 +1445,7 @@ Geolocation::WatchPosition(GeoPositionCallback& aCallback,
|
||||
*aRv);
|
||||
|
||||
if (!sGeoEnabled) {
|
||||
GPSLOG("request allow event");
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
|
||||
NS_DispatchToMainThread(ev);
|
||||
return NS_OK;
|
||||
@ -1447,8 +1568,7 @@ Geolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
|
||||
{
|
||||
if (Preferences::GetBool("geo.prompt.testing", false)) {
|
||||
bool allow = Preferences::GetBool("geo.prompt.testing.allow", false);
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow,
|
||||
request);
|
||||
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow, request);
|
||||
NS_DispatchToMainThread(ev);
|
||||
return true;
|
||||
}
|
||||
|
461
dom/geolocation/nsGeolocationSettings.cpp
Normal file
461
dom/geolocation/nsGeolocationSettings.cpp
Normal file
@ -0,0 +1,461 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "nsISettingsService.h"
|
||||
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsGeolocationSettings.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/SettingChangeNotificationBinding.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "prdtoa.h"
|
||||
|
||||
#define GEO_ALA_TYPE_VALUE_PRECISE "precise"
|
||||
#define GEO_ALA_TYPE_VALUE_APPROX "blur"
|
||||
#define GEO_ALA_TYPE_VALUE_FIXED "user-defined"
|
||||
#define GEO_ALA_TYPE_VALUE_NONE "no-location"
|
||||
|
||||
using mozilla::unused;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsGeolocationSettings, nsIObserver)
|
||||
|
||||
StaticRefPtr<nsGeolocationSettings> nsGeolocationSettings::sSettings;
|
||||
|
||||
already_AddRefed<nsGeolocationSettings>
|
||||
nsGeolocationSettings::GetGeolocationSettings()
|
||||
{
|
||||
// this singleton is only needed in the parent process...
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<nsGeolocationSettings> result;
|
||||
if (nsGeolocationSettings::sSettings) {
|
||||
result = nsGeolocationSettings::sSettings;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
result = new nsGeolocationSettings();
|
||||
if (NS_FAILED(result->Init())) {
|
||||
return nullptr;
|
||||
}
|
||||
ClearOnShutdown(&nsGeolocationSettings::sSettings);
|
||||
nsGeolocationSettings::sSettings = result;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
nsresult nsGeolocationSettings::Init()
|
||||
{
|
||||
// query for the current settings...
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (!obs) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// hook up observers
|
||||
obs->AddObserver(this, "quit-application", false);
|
||||
obs->AddObserver(this, "mozsettings-changed", false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationSettings::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
// remove observers
|
||||
if (!strcmp("quit-application", aTopic)) {
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, "quit-application");
|
||||
obs->RemoveObserver(this, "mozsettings-changed");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp("mozsettings-changed", aTopic)) {
|
||||
HandleMozsettingsChanged(aSubject);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
GeolocationSetting
|
||||
nsGeolocationSettings::LookupGeolocationSetting(int32_t aWatchID)
|
||||
{
|
||||
nsCString *origin;
|
||||
if (!mCurrentWatches.Get(aWatchID, &origin) || !origin) {
|
||||
return mGlobalSetting;
|
||||
}
|
||||
|
||||
// if there is no per-app setting for the given origin, this will
|
||||
// set gb == nullptr
|
||||
GeolocationSetting const * const gb =
|
||||
mPerOriginSettings.Get(NS_ConvertUTF8toUTF16(*origin));
|
||||
|
||||
// return a copy of the per-app or global settings
|
||||
return gb ? *gb : mGlobalSetting;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleGeolocationSettingsChange(const nsAString& aKey,
|
||||
const JS::Value& aVal)
|
||||
{
|
||||
if (aKey.EqualsASCII(GEO_ALA_ENABLED)) {
|
||||
HandleGeolocationAlaEnabledChange(aVal);
|
||||
} else if (aKey.EqualsASCII(GEO_ALA_TYPE)) {
|
||||
mGlobalSetting.HandleTypeChange(aVal);
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
} else if (aKey.EqualsASCII(GEO_ALA_APPROX_DISTANCE)) {
|
||||
mGlobalSetting.HandleApproxDistanceChange(aVal);
|
||||
#endif
|
||||
} else if (aKey.EqualsASCII(GEO_ALA_FIXED_COORDS)) {
|
||||
mGlobalSetting.HandleFixedCoordsChange(aVal);
|
||||
} else if (aKey.EqualsASCII(GEO_ALA_APP_SETTINGS)) {
|
||||
HandleGeolocationPerOriginSettingsChange(aVal);
|
||||
} else if (aKey.EqualsASCII(GEO_ALA_ALWAYS_PRECISE)) {
|
||||
HandleGeolocationAlwaysPreciseChange(aVal);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleMozsettingsChanged(nsISupports* aSubject)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
RootedDictionary<SettingChangeNotification> setting(cx);
|
||||
if (!WrappedJSToDictionary(cx, aSubject, setting)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPSLOG("mozsettings changed: %s", NS_ConvertUTF16toUTF8(setting.mKey).get());
|
||||
|
||||
// and handle the geolocation settings change...
|
||||
HandleGeolocationSettingsChange(setting.mKey, setting.mValue);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleGeolocationSettingsError(const nsAString& aName)
|
||||
{
|
||||
if (aName.EqualsASCII(GEO_ALA_ENABLED)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_ENABLED "'");
|
||||
} else if (aName.EqualsASCII(GEO_ALA_TYPE)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_TYPE "'");
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
} else if (aName.EqualsASCII(GEO_ALA_APPROX_DISTANCE)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_APPROX_DISTANCE "'");
|
||||
#endif
|
||||
} else if (aName.EqualsASCII(GEO_ALA_FIXED_COORDS)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_FIXED_COORDS "'");
|
||||
} else if (aName.EqualsASCII(GEO_ALA_APP_SETTINGS)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_APP_SETTINGS "'");
|
||||
} else if (aName.EqualsASCII(GEO_ALA_ALWAYS_PRECISE)) {
|
||||
GPSLOG("Unable to get value for '" GEO_ALA_ALWAYS_PRECISE "'");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::PutWatchOrigin(int32_t aWatchID,
|
||||
const nsCString& aOrigin)
|
||||
{
|
||||
if (aWatchID < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPSLOG("mapping watch ID %d to origin %s", aWatchID, aOrigin.get());
|
||||
mCurrentWatches.Put(static_cast<uint32_t>(aWatchID), new nsCString(aOrigin));
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::RemoveWatchOrigin(int32_t aWatchID)
|
||||
{
|
||||
GPSLOG("unmapping watch ID %d", aWatchID);
|
||||
mCurrentWatches.Remove(static_cast<uint32_t>(aWatchID));
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::GetWatchOrigin(int32_t aWatchID, nsCString& aOrigin)
|
||||
{
|
||||
nsCString *str;
|
||||
if (!mCurrentWatches.Get(aWatchID, &str) || !str) {
|
||||
return;
|
||||
}
|
||||
aOrigin = *str;
|
||||
GPSLOG("returning origin %s for watch ID %d", aOrigin.get(), aWatchID);
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleGeolocationAlaEnabledChange(const JS::Value& aVal)
|
||||
{
|
||||
if (!aVal.isBoolean()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAlaEnabled = aVal.toBoolean();
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value& aVal)
|
||||
{
|
||||
if (!aVal.isObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the hash table
|
||||
mPerOriginSettings.Clear();
|
||||
|
||||
// enumerate the array
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JSObject*> obj(cx, &aVal.toObject());
|
||||
JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj));
|
||||
|
||||
// if we get no ids then the exception list is empty and we can return here.
|
||||
if (!ids)
|
||||
return;
|
||||
|
||||
// go through all of the objects in the exceptions dictionary
|
||||
for (size_t i = 0; i < ids.length(); i++) {
|
||||
JS::RootedId id(cx);
|
||||
id = ids[i];
|
||||
|
||||
JS::RootedValue v(cx);
|
||||
if (!JS_IdToValue(cx, id, &v) || !v.isString())
|
||||
continue;
|
||||
|
||||
JS::RootedString str(cx, v.toString());
|
||||
if (!str)
|
||||
continue;
|
||||
|
||||
// get the origin for the app
|
||||
nsString origin;
|
||||
if (!AssignJSString(cx, origin, str))
|
||||
continue;
|
||||
|
||||
// if it is an app that is always precise, skip it
|
||||
if (mAlwaysPreciseApps.Contains(origin))
|
||||
continue;
|
||||
|
||||
// get the app setting object
|
||||
JS::RootedValue propertyValue(cx);
|
||||
if (!JS_GetPropertyById(cx, obj, id, &propertyValue) || !propertyValue.isObject())
|
||||
continue;
|
||||
JS::RootedObject settingObj(cx, &propertyValue.toObject());
|
||||
|
||||
GeolocationSetting *settings = new GeolocationSetting(origin);
|
||||
GPSLOG("adding exception for %s", NS_ConvertUTF16toUTF8(origin).get());
|
||||
|
||||
// get the geolocation type
|
||||
JS::RootedValue fm(cx);
|
||||
if (JS_GetProperty(cx, settingObj, "type", &fm)) {
|
||||
settings->HandleTypeChange(fm);
|
||||
}
|
||||
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
// get the approximate distance if there is one
|
||||
JS::RootedValue distance(cx);
|
||||
if (JS_GetProperty(cx, settingObj, "distance", &distance)) {
|
||||
settings->HandleApproxDistanceChange(distance);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get and parse the coords, if any
|
||||
JS::RootedValue coords(cx);
|
||||
if (JS_GetProperty(cx, settingObj, "coords", &coords)) {
|
||||
settings->HandleFixedCoordsChange(coords);
|
||||
}
|
||||
|
||||
// add the per-app setting object to the hashtable
|
||||
mPerOriginSettings.Put(origin, settings);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal)
|
||||
{
|
||||
if (!aVal.isObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the list of apps that are always precise
|
||||
mAlwaysPreciseApps.Clear();
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JSObject*> obj(cx, &aVal.toObject());
|
||||
if (!JS_IsArrayObject(cx, obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t length;
|
||||
if (!JS_GetArrayLength(cx, obj, &length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// process the list of apps...
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
JS::RootedValue value(cx);
|
||||
|
||||
if (!JS_GetElement(cx, obj, i, &value) || !value.isString()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsString origin;
|
||||
if (!AssignJSString(cx, origin, value.toString())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GPSLOG("adding always precise for %s", NS_ConvertUTF16toUTF8(origin).get());
|
||||
|
||||
// add the origin to the list of apps that will always receive
|
||||
// precise location information
|
||||
mAlwaysPreciseApps.AppendElement(origin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
GeolocationSetting::HandleTypeChange(const JS::Value& aVal)
|
||||
{
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
nsString str;
|
||||
if (!aVal.isString() || !AssignJSString(cx, str, aVal.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeolocationFuzzMethod fm = GEO_ALA_TYPE_DEFAULT;
|
||||
if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_PRECISE)) {
|
||||
fm = GEO_ALA_TYPE_PRECISE;
|
||||
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_APPROX)) {
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
fm = GEO_ALA_TYPE_APPROX;
|
||||
#else
|
||||
// we are loading a profile from a build with MOZ_APPROX_LOCATION
|
||||
// enabled, then we need to force the type to a sane value
|
||||
fm = GEO_ALA_TYPE_NONE;
|
||||
#endif
|
||||
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_FIXED)) {
|
||||
fm = GEO_ALA_TYPE_FIXED;
|
||||
} else if (str.EqualsASCII(GEO_ALA_TYPE_VALUE_NONE)) {
|
||||
fm = GEO_ALA_TYPE_NONE;
|
||||
}
|
||||
|
||||
if ((fm >= GEO_ALA_TYPE_FIRST) && (fm <= GEO_ALA_TYPE_LAST)) {
|
||||
GPSLOG("changing type for %s to %s (%d)",
|
||||
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
|
||||
NS_ConvertUTF16toUTF8(str).get(),
|
||||
static_cast<int>(fm));
|
||||
mFuzzMethod = fm;
|
||||
}
|
||||
|
||||
// based on the new type, we need to clean up the other settings
|
||||
switch (mFuzzMethod) {
|
||||
case GEO_ALA_TYPE_PRECISE:
|
||||
case GEO_ALA_TYPE_NONE:
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
mDistance = 0;
|
||||
#endif
|
||||
mLatitude = 0.0;
|
||||
mLongitude = 0.0;
|
||||
break;
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
case GEO_ALA_TYPE_APPROX:
|
||||
mLatitude = 0.0;
|
||||
mLongitude = 0.0;
|
||||
break;
|
||||
#endif
|
||||
case GEO_ALA_TYPE_FIXED:
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
mDistance = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
void
|
||||
GeolocationSetting::HandleApproxDistanceChange(const JS::Value& aVal)
|
||||
{
|
||||
if (!aVal.isInt32()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPSLOG("changing approx distance for %s to %d",
|
||||
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
|
||||
aVal.toInt32());
|
||||
|
||||
// set the approximate distance
|
||||
mDistance = aVal.toInt32();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
GeolocationSetting::HandleFixedCoordsChange(const JS::Value& aVal)
|
||||
{
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
nsString str;
|
||||
if (!aVal.isString() || !AssignJSString(cx, str, aVal.toString()) || str.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the string and store the global lat/lon
|
||||
// the @ character is present in the GPS coord strings we receive
|
||||
int32_t const comma = str.Find(",");
|
||||
if ( (str.CharAt(0) != '@') || (comma == -1) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsString slat(Substring(str, 1, comma));
|
||||
nsString slon(Substring(str, comma + 1));
|
||||
double lat = slat.ToDouble(&rv);
|
||||
NS_ENSURE_SUCCESS(rv,);
|
||||
double lon = slon.ToDouble(&rv);
|
||||
NS_ENSURE_SUCCESS(rv,);
|
||||
mLatitude = lat;
|
||||
mLongitude = lon;
|
||||
|
||||
GPSLOG("changing coords for %s to %s (%f, %f)",
|
||||
(mOrigin.IsEmpty() ? "global" : NS_ConvertUTF16toUTF8(mOrigin).get()),
|
||||
NS_ConvertUTF16toUTF8(str).get(),
|
||||
mLatitude, mLongitude);
|
||||
}
|
||||
|
165
dom/geolocation/nsGeolocationSettings.h
Normal file
165
dom/geolocation/nsGeolocationSettings.h
Normal file
@ -0,0 +1,165 @@
|
||||
/* -*- 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 nsGeolocationSettings_h
|
||||
#define nsGeolocationSettings_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#if (defined(MOZ_GPS_DEBUG) && defined(ANDROID))
|
||||
#include <android/log.h>
|
||||
#define GPSLOG(fmt, ...) __android_log_print(ANDROID_LOG_WARN, "GPS", "%12s:%-5d " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define GPSLOG(...) {;}
|
||||
#endif // MOZ_GPS_DEBUG && ANDROID
|
||||
|
||||
// The settings key.
|
||||
#define GEO_ENABLED "geolocation.enabled"
|
||||
#define GEO_ALA_ENABLED "ala.settings.enabled"
|
||||
#define GEO_ALA_TYPE "geolocation.type"
|
||||
#define GEO_ALA_FIXED_COORDS "geolocation.fixed_coords"
|
||||
#define GEO_ALA_APP_SETTINGS "geolocation.app_settings"
|
||||
#define GEO_ALA_ALWAYS_PRECISE "geolocation.always_precise"
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
#define GEO_ALA_APPROX_DISTANCE "geolocation.approx_distance"
|
||||
#endif
|
||||
|
||||
enum GeolocationFuzzMethod {
|
||||
GEO_ALA_TYPE_PRECISE, // default, GPS/AGPS location
|
||||
GEO_ALA_TYPE_FIXED, // user supplied lat/long
|
||||
GEO_ALA_TYPE_NONE, // no location given
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
GEO_ALA_TYPE_APPROX // approximate, grid-based location
|
||||
#endif
|
||||
};
|
||||
|
||||
#define GEO_ALA_TYPE_DEFAULT (GEO_ALA_TYPE_PRECISE)
|
||||
#define GEO_ALA_TYPE_FIRST (GEO_ALA_TYPE_PRECISE)
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
#define GEO_ALA_TYPE_LAST (GEO_ALA_TYPE_APPROX)
|
||||
#else
|
||||
#define GEO_ALA_TYPE_LAST (GEO_ALA_TYPE_NONE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Simple class for holding the geolocation settings values.
|
||||
*/
|
||||
|
||||
class GeolocationSetting MOZ_FINAL {
|
||||
public:
|
||||
GeolocationSetting(const nsString& aOrigin) :
|
||||
mFuzzMethod(GEO_ALA_TYPE_DEFAULT),
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
mDistance(0),
|
||||
#endif
|
||||
mLatitude(0.0),
|
||||
mLongitude(0.0),
|
||||
mOrigin(aOrigin) {}
|
||||
|
||||
GeolocationSetting(const GeolocationSetting& rhs) :
|
||||
mFuzzMethod(rhs.mFuzzMethod),
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
mDistance(rhs.mDistance),
|
||||
#endif
|
||||
mLatitude(rhs.mLatitude),
|
||||
mLongitude(rhs.mLongitude),
|
||||
mOrigin(rhs.mOrigin) {}
|
||||
|
||||
~GeolocationSetting() {}
|
||||
|
||||
GeolocationSetting& operator=(const GeolocationSetting& rhs) {
|
||||
mFuzzMethod = rhs.mFuzzMethod;
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
mDistance = rhs.mDistance;
|
||||
#endif
|
||||
mLatitude = rhs.mLatitude;
|
||||
mLongitude = rhs.mLongitude;
|
||||
mOrigin = rhs.mOrigin;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void HandleTypeChange(const JS::Value& aVal);
|
||||
void HandleApproxDistanceChange(const JS::Value& aVal);
|
||||
void HandleFixedCoordsChange(const JS::Value& aVal);
|
||||
|
||||
inline GeolocationFuzzMethod GetType() const { return mFuzzMethod; }
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
inline int32_t GetApproxDistance() const { return mDistance; }
|
||||
#endif
|
||||
inline double GetFixedLatitude() const { return mLatitude; }
|
||||
inline double GetFixedLongitude() const { return mLongitude; }
|
||||
inline const nsString& GetOrigin() const { return mOrigin; }
|
||||
|
||||
private:
|
||||
GeolocationSetting() {} // can't default construct
|
||||
GeolocationFuzzMethod mFuzzMethod;
|
||||
#ifdef MOZ_APPROX_LOCATION
|
||||
int32_t mDistance;
|
||||
#endif
|
||||
double mLatitude,
|
||||
mLongitude;
|
||||
nsString mOrigin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton that holds the global and per-origin geolocation settings.
|
||||
*/
|
||||
class nsGeolocationSettings MOZ_FINAL : public nsIObserver
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<nsGeolocationSettings> GetGeolocationSettings();
|
||||
static mozilla::StaticRefPtr<nsGeolocationSettings> sSettings;
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsGeolocationSettings() : mAlaEnabled(false), mGlobalSetting(NullString()) {}
|
||||
nsresult Init();
|
||||
|
||||
void HandleGeolocationSettingsChange(const nsAString& aKey, const JS::Value& aVal);
|
||||
void HandleGeolocationSettingsError(const nsAString& aName);
|
||||
|
||||
void PutWatchOrigin(int32_t aWatchID, const nsCString& aOrigin);
|
||||
void RemoveWatchOrigin(int32_t aWatchID);
|
||||
void GetWatchOrigin(int32_t aWatchID, nsCString& aOrigin);
|
||||
inline bool IsAlaEnabled() const { return mAlaEnabled; }
|
||||
|
||||
// given a watch ID, retrieve the geolocation settings. the watch ID is
|
||||
// mapped to the origin of the listener/request which is then used to
|
||||
// retreive the geolocation settings for the origin.
|
||||
// if the origin is in the always-precise list, the settings will always be
|
||||
// 'precise'. if the origin has origin-specific settings, that will be returned
|
||||
// otherwise the global geolocation settings will be returned.
|
||||
// NOTE: this returns a copy of the settings to enforce read-only client access
|
||||
GeolocationSetting LookupGeolocationSetting(int32_t aWatchID);
|
||||
|
||||
private:
|
||||
~nsGeolocationSettings() {}
|
||||
nsGeolocationSettings(const nsGeolocationSettings&) :
|
||||
mGlobalSetting(NullString()) {} // can't copy obj
|
||||
|
||||
void HandleMozsettingsChanged(nsISupports* aSubject);
|
||||
void HandleGeolocationAlaEnabledChange(const JS::Value& aVal);
|
||||
void HandleGeolocationPerOriginSettingsChange(const JS::Value& aVal);
|
||||
void HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal);
|
||||
|
||||
private:
|
||||
bool mAlaEnabled;
|
||||
GeolocationSetting mGlobalSetting;
|
||||
nsClassHashtable<nsStringHashKey, GeolocationSetting> mPerOriginSettings;
|
||||
nsTArray<nsString> mAlwaysPreciseApps;
|
||||
nsClassHashtable<nsUint32HashKey, nsCString> mCurrentWatches;
|
||||
};
|
||||
|
||||
#endif /* nsGeolocationSettings_h */
|
||||
|
@ -7269,6 +7269,8 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
nsTArray<nsFilePickerFilter> filters;
|
||||
nsString allExtensionsList;
|
||||
|
||||
bool allFiltersAreValid = true;
|
||||
|
||||
// Retrieve all filters
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentSubstring& token = tokenizer.nextToken();
|
||||
@ -7302,6 +7304,7 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
EmptyCString(), // No extension
|
||||
getter_AddRefs(mimeInfo))) ||
|
||||
!mimeInfo) {
|
||||
allFiltersAreValid = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -7334,6 +7337,7 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
|
||||
if (!filterMask && (extensionListStr.IsEmpty() || filterName.IsEmpty())) {
|
||||
// No valid filter found
|
||||
allFiltersAreValid = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -7363,8 +7367,7 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
filePicker->AppendFilter(title, allExtensionsList);
|
||||
}
|
||||
|
||||
// Add each filter, and check if all filters are trusted
|
||||
bool allFilterAreTrusted = true;
|
||||
// Add each filter
|
||||
for (uint32_t i = 0; i < filters.Length(); ++i) {
|
||||
const nsFilePickerFilter& filter = filters[i];
|
||||
if (filter.mFilterMask) {
|
||||
@ -7372,12 +7375,11 @@ HTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
} else {
|
||||
filePicker->AppendFilter(filter.mTitle, filter.mFilter);
|
||||
}
|
||||
allFilterAreTrusted &= filter.mIsTrusted;
|
||||
}
|
||||
|
||||
// If all filters are trusted, select the first filter as default;
|
||||
// If all filters are known/valid, select the first filter as default;
|
||||
// otherwise filterAll will remain the default filter
|
||||
if (filters.Length() >= 1 && allFilterAreTrusted) {
|
||||
if (filters.Length() >= 1 && allFiltersAreValid) {
|
||||
// |filterAll| will always use index=0 so we need to set index=1 as the
|
||||
// current filter.
|
||||
filePicker->SetFilterIndex(1);
|
||||
|
@ -1361,28 +1361,23 @@ private:
|
||||
|
||||
struct nsFilePickerFilter {
|
||||
nsFilePickerFilter()
|
||||
: mFilterMask(0), mIsTrusted(false) {}
|
||||
: mFilterMask(0) {}
|
||||
|
||||
explicit nsFilePickerFilter(int32_t aFilterMask)
|
||||
: mFilterMask(aFilterMask), mIsTrusted(true) {}
|
||||
: mFilterMask(aFilterMask) {}
|
||||
|
||||
nsFilePickerFilter(const nsString& aTitle,
|
||||
const nsString& aFilter,
|
||||
const bool aIsTrusted = false)
|
||||
: mFilterMask(0), mTitle(aTitle), mFilter(aFilter), mIsTrusted(aIsTrusted) {}
|
||||
const nsString& aFilter)
|
||||
: mFilterMask(0), mTitle(aTitle), mFilter(aFilter) {}
|
||||
|
||||
nsFilePickerFilter(const nsFilePickerFilter& other) {
|
||||
mFilterMask = other.mFilterMask;
|
||||
mTitle = other.mTitle;
|
||||
mFilter = other.mFilter;
|
||||
mIsTrusted = other.mIsTrusted;
|
||||
}
|
||||
|
||||
bool operator== (const nsFilePickerFilter& other) const {
|
||||
if ((mFilter == other.mFilter) && (mFilterMask == other.mFilterMask)) {
|
||||
NS_ASSERTION(mIsTrusted == other.mIsTrusted,
|
||||
"Filter with similar list of extensions and mask should"
|
||||
" have the same trusted flag value");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -1395,12 +1390,6 @@ private:
|
||||
// ignored
|
||||
nsString mTitle;
|
||||
nsString mFilter;
|
||||
// mIsTrusted is true if mime type comes from a "trusted" source (e.g. our
|
||||
// hard-coded set).
|
||||
// false means it may come from an "untrusted" source (e.g. OS mime types
|
||||
// mapping, which can be different accross OS, user's personal configuration, ...)
|
||||
// For now, only mask filters are considered to be "trusted".
|
||||
bool mIsTrusted;
|
||||
};
|
||||
|
||||
class nsFilePickerShownCallback
|
||||
|
@ -126,11 +126,13 @@ nsDOMStringMap::NamedDeleter(const nsAString& aProp, bool& found)
|
||||
{
|
||||
// Currently removing property, attribute is already removed.
|
||||
if (mRemovingProp) {
|
||||
found = false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString attr;
|
||||
if (!DataPropToAttr(aProp, attr)) {
|
||||
found = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ var testData = [["a", 1, MockFilePicker.filterImages, 1],
|
||||
["e", 3, imageExtensionList + "; " + videoExtensionList, 1],
|
||||
["f", 3, audioExtensionList + "; " + videoExtensionList, 1],
|
||||
["g", 4, imageExtensionList + "; " + audioExtensionList + "; " + videoExtensionList, 1],
|
||||
["h", 1, MockFilePicker.filterImages, 1],
|
||||
["i", 1, MockFilePicker.filterVideo, 1],
|
||||
["h", 1, MockFilePicker.filterImages, 0],
|
||||
["i", 1, MockFilePicker.filterVideo, 0],
|
||||
["j", 1, MockFilePicker.filterAudio, 1],
|
||||
["k", 3, "*.gif; *.png", 0],
|
||||
["l", 4, imageExtensionList + "; " + "*.gif; *.png", 0],
|
||||
["m", 1, "*.gif", 0],
|
||||
["k", 3, "*.gif; *.png", 1],
|
||||
["l", 4, imageExtensionList + "; " + "*.gif; *.png", 1],
|
||||
["m", 1, "*.gif", 1],
|
||||
["n", 0, undefined, 0],
|
||||
["z", 0, undefined, 0],
|
||||
["hidden", 0, undefined, 0],
|
||||
|
@ -55,9 +55,6 @@ taskHelper.push(function testPinChangeSuccess() {
|
||||
};
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
is(request.result.lockType, "pin");
|
||||
is(request.result.success, true);
|
||||
|
||||
taskHelper.runNext();
|
||||
};
|
||||
});
|
||||
@ -70,8 +67,6 @@ taskHelper.push(function testPinCardLockRetryCount() {
|
||||
'request instanceof ' + request.constructor);
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
is(request.result.lockType, 'pin',
|
||||
'lockType is ' + request.result.lockType);
|
||||
ok(request.result.retryCount >= 0,
|
||||
'retryCount is ' + request.result.retryCount);
|
||||
taskHelper.runNext();
|
||||
@ -94,8 +89,6 @@ taskHelper.push(function testPukCardLockRetryCount() {
|
||||
'request instanceof ' + request.constructor);
|
||||
|
||||
request.onsuccess = function onsuccess() {
|
||||
is(request.result.lockType, 'puk',
|
||||
'lockType is ' + request.result.lockType);
|
||||
ok(request.result.retryCount >= 0,
|
||||
'retryCount is ' + request.result.retryCount);
|
||||
taskHelper.runNext();
|
||||
|
@ -10,7 +10,7 @@ support-files =
|
||||
|
||||
[conformancetest/test_event.html]
|
||||
[conformancetest/test_runtest.html]
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #b2g(takes too long) b2g-debug(takes too long) b2g-desktop(takes too long)
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') || e10s #b2g(takes too long) b2g-debug(takes too long) b2g-desktop(takes too long)
|
||||
[selecttest/test_Document-open.html]
|
||||
[selecttest/test_addRange.html]
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(bug 775227) b2g(oom?, bug 775227) b2g-debug(oom?, bug 775227) b2g-desktop(oom?, bug 775227)
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "ActorsParent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "CheckQuotaHelper.h"
|
||||
#include "FileInfo.h"
|
||||
#include "FileManager.h"
|
||||
#include "IDBObjectStore.h"
|
||||
@ -3892,6 +3891,8 @@ protected:
|
||||
nsCString mOrigin;
|
||||
nsCString mDatabaseId;
|
||||
State mState;
|
||||
bool mIsApp;
|
||||
bool mHasUnlimStoragePerm;
|
||||
bool mEnforcingQuota;
|
||||
const bool mDeleting;
|
||||
bool mBlockedQuotaManager;
|
||||
@ -5938,6 +5939,12 @@ Factory::AllocPBackgroundIDBFactoryRequestParent(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo &&
|
||||
metadata.persistenceType() != PERSISTENCE_TYPE_PERSISTENT)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ContentParent> contentParent =
|
||||
BackgroundParent::GetContentParent(Manager());
|
||||
|
||||
@ -10442,6 +10449,8 @@ FactoryOp::FactoryOp(Factory* aFactory,
|
||||
, mContentParent(Move(aContentParent))
|
||||
, mCommonParams(aCommonParams)
|
||||
, mState(State_Initial)
|
||||
, mIsApp(false)
|
||||
, mHasUnlimStoragePerm(false)
|
||||
, mEnforcingQuota(true)
|
||||
, mDeleting(aDeleting)
|
||||
, mBlockedQuotaManager(false)
|
||||
@ -10687,11 +10696,14 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
PersistenceType persistenceType = mCommonParams.metadata().persistenceType();
|
||||
|
||||
const PrincipalInfo& principalInfo = mCommonParams.principalInfo();
|
||||
MOZ_ASSERT(principalInfo.type() != PrincipalInfo::TNullPrincipalInfo);
|
||||
|
||||
if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
|
||||
MOZ_ASSERT(mState == State_Initial);
|
||||
MOZ_ASSERT(persistenceType == PERSISTENCE_TYPE_PERSISTENT);
|
||||
|
||||
if (aContentParent) {
|
||||
// Check to make sure that the child process has access to the database it
|
||||
@ -10740,8 +10752,12 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
||||
}
|
||||
|
||||
if (State_Initial == mState) {
|
||||
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, nullptr, nullptr);
|
||||
mEnforcingQuota = false;
|
||||
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, &mIsApp,
|
||||
&mHasUnlimStoragePerm);
|
||||
|
||||
mEnforcingQuota =
|
||||
QuotaManager::IsQuotaEnforced(persistenceType, mOrigin, mIsApp,
|
||||
mHasUnlimStoragePerm);
|
||||
}
|
||||
|
||||
*aPermission = PermissionRequestBase::kPermissionAllowed;
|
||||
@ -10759,13 +10775,11 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
||||
|
||||
PermissionRequestBase::PermissionValue permission;
|
||||
|
||||
if (mCommonParams.metadata().persistenceType() ==
|
||||
PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (persistenceType == PERSISTENCE_TYPE_TEMPORARY) {
|
||||
// Temporary storage doesn't need to check the permission.
|
||||
permission = PermissionRequestBase::kPermissionAllowed;
|
||||
} else {
|
||||
MOZ_ASSERT(mCommonParams.metadata().persistenceType() ==
|
||||
PERSISTENCE_TYPE_PERSISTENT);
|
||||
MOZ_ASSERT(persistenceType == PERSISTENCE_TYPE_PERSISTENT);
|
||||
|
||||
#ifdef MOZ_CHILD_PERMISSIONS
|
||||
if (aContentParent) {
|
||||
@ -10791,22 +10805,16 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
||||
|
||||
if (permission != PermissionRequestBase::kPermissionDenied &&
|
||||
State_Initial == mState) {
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
|
||||
nullptr, nullptr);
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, persistenceType, &mGroup,
|
||||
&mOrigin, &mIsApp,
|
||||
&mHasUnlimStoragePerm);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (permission == PermissionRequestBase::kPermissionAllowed &&
|
||||
mEnforcingQuota)
|
||||
{
|
||||
// If we're running from a window then we should check the quota permission
|
||||
// as well.
|
||||
uint32_t quotaPermission = CheckQuotaHelper::GetQuotaPermission(principal);
|
||||
if (quotaPermission == nsIPermissionManager::ALLOW_ACTION) {
|
||||
mEnforcingQuota = false;
|
||||
}
|
||||
mEnforcingQuota =
|
||||
QuotaManager::IsQuotaEnforced(persistenceType, mOrigin, mIsApp,
|
||||
mHasUnlimStoragePerm);
|
||||
}
|
||||
|
||||
*aPermission = permission;
|
||||
@ -11211,7 +11219,8 @@ OpenDatabaseOp::DoDatabaseWork()
|
||||
quotaManager->EnsureOriginIsInitialized(persistenceType,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mEnforcingQuota,
|
||||
mIsApp,
|
||||
mHasUnlimStoragePerm,
|
||||
getter_AddRefs(dbDirectory));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -973,8 +973,10 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
PersistenceType persistenceType = mSpec->metadata().persistenceType();
|
||||
|
||||
if (aPersistenceType) {
|
||||
*aPersistenceType = mSpec->metadata().persistenceType();
|
||||
*aPersistenceType = persistenceType;
|
||||
MOZ_ASSERT(*aPersistenceType != PERSISTENCE_TYPE_INVALID);
|
||||
}
|
||||
|
||||
@ -998,6 +1000,7 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
|
||||
}
|
||||
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal,
|
||||
persistenceType,
|
||||
nullptr,
|
||||
&aOrigin,
|
||||
nullptr,
|
||||
|
@ -483,8 +483,7 @@ IDBFactory::OpenInternal(nsIPrincipal* aPrincipal,
|
||||
persistenceType = PERSISTENCE_TYPE_PERSISTENT;
|
||||
persistenceTypeIsExplicit = false;
|
||||
} else {
|
||||
persistenceType =
|
||||
PersistenceTypeFromStorage(aStorageType, PERSISTENCE_TYPE_PERSISTENT);
|
||||
persistenceType = PersistenceTypeFromStorage(aStorageType);
|
||||
persistenceTypeIsExplicit = aStorageType.WasPassed();
|
||||
}
|
||||
|
||||
|
@ -157,9 +157,15 @@ IDBMutableFile::Create(IDBDatabase* aDatabase,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DatabaseSpec* spec = aDatabase->Spec();
|
||||
MOZ_ASSERT(spec);
|
||||
|
||||
PersistenceType persistenceType = spec->metadata().persistenceType();
|
||||
|
||||
nsCString group;
|
||||
nsCString origin;
|
||||
if (NS_WARN_IF(NS_FAILED(QuotaManager::GetInfoFromPrincipal(principal,
|
||||
persistenceType,
|
||||
&group,
|
||||
&origin,
|
||||
nullptr,
|
||||
@ -167,11 +173,6 @@ IDBMutableFile::Create(IDBDatabase* aDatabase,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DatabaseSpec* spec = aDatabase->Spec();
|
||||
MOZ_ASSERT(spec);
|
||||
|
||||
PersistenceType persistenceType = spec->metadata().persistenceType();
|
||||
|
||||
nsCString storageId;
|
||||
QuotaManager::GetStorageId(persistenceType,
|
||||
origin,
|
||||
|
@ -93,7 +93,6 @@ FAIL_ON_WARNINGS = True
|
||||
LOCAL_INCLUDES += [
|
||||
'/db/sqlite3/src',
|
||||
'/dom/base',
|
||||
'/dom/quota',
|
||||
'/dom/storage',
|
||||
'/ipc/glue',
|
||||
'/xpcom/build',
|
||||
|
@ -148,7 +148,9 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_deleteDatabase_interactions.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_disabled_quota_prompt.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
# Test temporarily disabled.
|
||||
skip-if = true
|
||||
# skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_error_events_abort_transactions.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_event_propagation.html]
|
||||
|
@ -3,8 +3,6 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
Components.utils.importGlobalProperties(['Blob']);
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
@ -37,6 +35,11 @@ function testSteps()
|
||||
const lastIndex = urls.length - 1;
|
||||
const lastUrl = urls[lastIndex].url;
|
||||
|
||||
const openDBOptions = [
|
||||
{ version: 1, storage: "temporary" },
|
||||
{ version: 1 }
|
||||
];
|
||||
|
||||
let quotaManager =
|
||||
Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(Components.interfaces.nsIQuotaManager);
|
||||
@ -46,8 +49,6 @@ function testSteps()
|
||||
|
||||
let dbSize = 0;
|
||||
|
||||
let databases = [];
|
||||
|
||||
function setLimit(limit) {
|
||||
if (limit) {
|
||||
SpecialPowers.setIntPref("dom.quotaManager.temporaryStorage.fixedLimit",
|
||||
@ -112,18 +113,66 @@ function testSteps()
|
||||
getUsageForUrl(lastUrl, grabUsageAndContinueHandler);
|
||||
dbSize = yield undefined;
|
||||
|
||||
setLimit(lastIndex * dbSize / 1024);
|
||||
quotaManager.clear();
|
||||
for (let options of openDBOptions) {
|
||||
setLimit(lastIndex * dbSize / 1024);
|
||||
quotaManager.clear();
|
||||
|
||||
info("Stage 1");
|
||||
info("Stage 1");
|
||||
|
||||
for (let i = 0; i < lastIndex; i++) {
|
||||
let data = urls[i];
|
||||
let databases = [];
|
||||
for (let i = 0; i < lastIndex; i++) {
|
||||
let data = urls[i];
|
||||
|
||||
info("Opening database for " + data.url);
|
||||
info("Opening database for " + data.url);
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(data.url), name,
|
||||
{ storage: "temporary" });
|
||||
request = indexedDB.openForPrincipal(getPrincipal(data.url), name,
|
||||
options);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "upgradeneeded", "Got correct event type");
|
||||
|
||||
let db = event.target.result;
|
||||
db.createObjectStore("foo", { });
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
databases.push(event.target.result);
|
||||
}
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, options);
|
||||
request.addEventListener("error", new ExpectError("QuotaExceededError"));
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield undefined;
|
||||
|
||||
checkUsage(1);
|
||||
yield undefined;
|
||||
|
||||
info("Stage 2");
|
||||
|
||||
for (let i = 1; i < urls.length; i++) {
|
||||
databases[i] = null;
|
||||
|
||||
scheduleGC();
|
||||
yield undefined;
|
||||
|
||||
// The origin access time is set to the current system time when the first
|
||||
// database for an origin is registered or the last one is unregistered.
|
||||
// The registration happens when the database object is being created and
|
||||
// the unregistration when it is unlinked/garbage collected.
|
||||
// Some older windows systems have the system time limited to a maximum
|
||||
// resolution of 10 or 15 milliseconds, so without a pause here we would
|
||||
// end up with origins with the same access time which would cause random
|
||||
// failures.
|
||||
setTimeout(function() { testGenerator.next(); }, 20);
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, options);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
@ -138,91 +187,43 @@ function testSteps()
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
databases.push(event.target.result);
|
||||
}
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||
{ storage: "temporary" });
|
||||
request.addEventListener("error", new ExpectError("QuotaExceededError"));
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield undefined;
|
||||
|
||||
checkUsage(1);
|
||||
yield undefined;
|
||||
|
||||
info("Stage 2");
|
||||
|
||||
for (let i = 1; i < urls.length; i++) {
|
||||
databases[i] = null;
|
||||
|
||||
scheduleGC();
|
||||
checkUsage(2);
|
||||
yield undefined;
|
||||
|
||||
// The origin access time is set to the current system time when the first
|
||||
// database for an origin is registered or the last one is unregistered.
|
||||
// The registration happens when the database object is being created and
|
||||
// the unregistration when it is unlinked/garbage collected.
|
||||
// Some older windows systems have the system time limited to a maximum
|
||||
// resolution of 10 or 15 milliseconds, so without a pause here we would
|
||||
// end up with origins with the same access time which would cause random
|
||||
// failures.
|
||||
setTimeout(function() { testGenerator.next(); }, 20);
|
||||
info("Stage 3");
|
||||
|
||||
setLimit(14 * dbSize / 1024);
|
||||
quotaManager.reset();
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, options);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
db = event.target.result;
|
||||
|
||||
checkUsage(3);
|
||||
yield undefined;
|
||||
|
||||
info("Stage 4");
|
||||
|
||||
let trans = db.transaction(["foo"], "readwrite");
|
||||
|
||||
let blob = new Blob(["bar"]);
|
||||
request = trans.objectStore("foo").add(blob, 42);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
trans.oncomplete = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
checkUsage(4);
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||
{ storage: "temporary" });
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "upgradeneeded", "Got correct event type");
|
||||
|
||||
let db = event.target.result;
|
||||
db.createObjectStore("foo", { });
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
checkUsage(2);
|
||||
yield undefined;
|
||||
|
||||
info("Stage 3");
|
||||
|
||||
setLimit(14 * dbSize / 1024);
|
||||
quotaManager.reset();
|
||||
|
||||
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||
{ storage: "temporary" });
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
db = event.target.result;
|
||||
|
||||
checkUsage(3);
|
||||
yield undefined;
|
||||
|
||||
info("Stage 4");
|
||||
|
||||
let trans = db.transaction(["foo"], "readwrite");
|
||||
|
||||
let blob = new Blob(["bar"]);
|
||||
request = trans.objectStore("foo").add(blob, 42);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
trans.oncomplete = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
checkUsage(4);
|
||||
yield undefined;
|
||||
|
||||
info("Cleanup");
|
||||
|
||||
setLimit();
|
||||
|
@ -251,22 +251,22 @@ this.Keyboard = {
|
||||
forwardEvent: function keyboardForwardEvent(newEventName, msg) {
|
||||
let mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
if (newEventName === 'Keyboard:FocusChange' &&
|
||||
msg.data.type === 'blur') {
|
||||
// A blur message can't be sent to the keyboard if the focus has
|
||||
// already taken away at first place.
|
||||
// This check is here to prevent problem caused by out-of-order
|
||||
// ipc messages from two processes.
|
||||
if (mm !== this.formMM) {
|
||||
return false;
|
||||
if (newEventName === 'Keyboard:FocusChange') {
|
||||
if (msg.data.type !== 'blur') { // Focus on a new input field
|
||||
// Set the formMM to the new message manager so that
|
||||
// message gets to the right form now on.
|
||||
this.formMM = mm;
|
||||
} else { // input is blurred
|
||||
// A blur message can't be sent to the keyboard if the focus has
|
||||
// already been taken away at first place.
|
||||
// This check is here to prevent problem caused by out-of-order
|
||||
// ipc messages from two processes.
|
||||
if (mm !== this.formMM) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.sendToKeyboard(newEventName, msg.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.formMM = mm;
|
||||
|
||||
this.sendToKeyboard(newEventName, msg.data);
|
||||
return true;
|
||||
},
|
||||
|
@ -261,7 +261,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/** Synthesize a mouse event. The event types supported are:
|
||||
* mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu,
|
||||
* MozMouseHitTest
|
||||
* MozMouseHittest
|
||||
*
|
||||
* Events are sent in coordinates offset by aX and aY from the window.
|
||||
*
|
||||
|
@ -86,6 +86,7 @@
|
||||
#include "nsConsoleService.h"
|
||||
#include "nsDebugImpl.h"
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsGeolocationSettings.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIAppsService.h"
|
||||
@ -3725,6 +3726,19 @@ ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
|
||||
// creation of a new listener.
|
||||
RecvRemoveGeolocationListener();
|
||||
mGeolocationWatchID = AddGeolocationListener(this, this, aHighAccuracy);
|
||||
|
||||
// let the the settings cache know the origin of the new listener
|
||||
nsAutoCString origin;
|
||||
// hint to the compiler to use the conversion operator to nsIPrincipal*
|
||||
nsCOMPtr<nsIPrincipal> principal = static_cast<nsIPrincipal*>(aPrincipal);
|
||||
if (!principal) {
|
||||
return true;
|
||||
}
|
||||
principal->GetOrigin(getter_Copies(origin));
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
if (gs) {
|
||||
gs->PutWatchOrigin(mGeolocationWatchID, origin);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3737,6 +3751,11 @@ ContentParent::RecvRemoveGeolocationListener()
|
||||
return true;
|
||||
}
|
||||
geo->ClearWatch(mGeolocationWatchID);
|
||||
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
if (gs) {
|
||||
gs->RemoveWatchOrigin(mGeolocationWatchID);
|
||||
}
|
||||
mGeolocationWatchID = -1;
|
||||
}
|
||||
return true;
|
||||
@ -3748,8 +3767,21 @@ ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
|
||||
// This should never be called without a listener already present,
|
||||
// so this check allows us to forgo securing privileges.
|
||||
if (mGeolocationWatchID != -1) {
|
||||
nsCString origin;
|
||||
nsRefPtr<nsGeolocationSettings> gs = nsGeolocationSettings::GetGeolocationSettings();
|
||||
// get the origin stored for the curent watch ID
|
||||
if (gs) {
|
||||
gs->GetWatchOrigin(mGeolocationWatchID, origin);
|
||||
}
|
||||
|
||||
// remove and recreate a new, high-accuracy listener
|
||||
RecvRemoveGeolocationListener();
|
||||
mGeolocationWatchID = AddGeolocationListener(this, this, aEnable);
|
||||
|
||||
// map the new watch ID to the origin
|
||||
if (gs) {
|
||||
gs->PutWatchOrigin(mGeolocationWatchID, origin);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -20,35 +20,6 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMMediaStream,
|
||||
DOMEventTargetHelper,
|
||||
mWindow,
|
||||
mTracks,
|
||||
mConsumersToKeepAlive);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream,
|
||||
mStreamNode)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
|
||||
|
||||
class DOMMediaStream::StreamListener : public MediaStreamListener {
|
||||
public:
|
||||
explicit StreamListener(DOMMediaStream* aStream)
|
||||
@ -132,6 +103,49 @@ private:
|
||||
DOMMediaStream* mStream;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMediaStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMediaStream,
|
||||
DOMEventTargetHelper)
|
||||
if (tmp->mListener) {
|
||||
// Make sure |mListener| cannot call back after |mTracks| is collected
|
||||
tmp->mListener->Forget();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMMediaStream,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream,
|
||||
mStreamNode)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
|
||||
|
||||
DOMMediaStream::DOMMediaStream()
|
||||
: mLogicalStreamStartTime(0),
|
||||
mStream(nullptr), mHintContents(0), mTrackTypesAvailable(0),
|
||||
|
@ -342,6 +342,7 @@ void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio,
|
||||
VERBOSE_LOG("writing %d frames of data to MediaStream for AudioData at %lld",
|
||||
aAudio->mFrames - int32_t(offset), aAudio->mTime);
|
||||
aStream->mAudioFramesWritten += aAudio->mFrames - int32_t(offset);
|
||||
aOutput->ApplyVolume(mVolume);
|
||||
}
|
||||
|
||||
static void WriteVideoToMediaStream(layers::Image* aImage,
|
||||
|
@ -112,8 +112,8 @@ RunOutputProtectionAPITests()
|
||||
}
|
||||
|
||||
// Report any failures in the callback function.
|
||||
for (auto& msg : failureMsgs) {
|
||||
FakeDecryptor::Message(msg);
|
||||
for (size_t i = 0; i < failureMsgs.size(); i++) {
|
||||
FakeDecryptor::Message(failureMsgs[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -95,11 +95,13 @@ void
|
||||
MediaSourceDecoder::Shutdown()
|
||||
{
|
||||
MSE_DEBUG("MediaSourceDecoder(%p)::Shutdown", this);
|
||||
MediaDecoder::Shutdown();
|
||||
|
||||
// Detach first so that TrackBuffers are unused on the main thread when
|
||||
// shut down on the decode task queue.
|
||||
if (mMediaSource) {
|
||||
mMediaSource->Detach();
|
||||
}
|
||||
|
||||
MediaDecoder::Shutdown();
|
||||
// Kick WaitForData out of its slumber.
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mon.NotifyAll();
|
||||
|
@ -72,6 +72,7 @@ skip-if = (toolkit == 'gonk') || (toolkit == 'android') || debug #bug 906752
|
||||
[test_bug894150.html]
|
||||
[test_bug956489.html]
|
||||
[test_bug964376.html]
|
||||
[test_bug966247.html]
|
||||
[test_bug972678.html]
|
||||
[test_bug1056032.html]
|
||||
skip-if = toolkit == 'android' # bug 1056706
|
||||
|
46
dom/media/webaudio/test/test_bug966247.html
Normal file
46
dom/media/webaudio/test/test_bug966247.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test whether an audio file played with a volume set to 0 plays silence</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<audio preload=none src="ting-48k-1ch.ogg" controls> </audio>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var count = 20;
|
||||
|
||||
function isSilent(b) {
|
||||
for (var i = 0; i < b.length; b++) {
|
||||
if (b[i] != 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var a = document.getElementsByTagName("audio")[0];
|
||||
a.volume = 0.0;
|
||||
var ac = new AudioContext();
|
||||
var measn = ac.createMediaElementSource(a);
|
||||
var sp = ac.createScriptProcessor();
|
||||
|
||||
sp.onaudioprocess = function(e) {
|
||||
var inputBuffer = e.inputBuffer.getChannelData(0);
|
||||
ok(isSilent(inputBuffer), "The volume is set to 0, so all the elements of the buffer are supposed to be equal to 0.0");
|
||||
}
|
||||
// Connect the MediaElementAudioSourceNode to the ScriptProcessorNode to check
|
||||
// the audio volume.
|
||||
measn.connect(sp);
|
||||
a.play();
|
||||
|
||||
a.addEventListener("ended", function() {
|
||||
sp.onaudioprocess = null;
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -478,6 +478,12 @@ MobileConnectionProvider.prototype = {
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* The design of this updating function is to update the attribute in
|
||||
* |aDestInfo| *only if* new data (e.g. aSrcInfo) contains the same attribute.
|
||||
* Thus, for the attribute in |aDestInfo| that isn't showed in |aSrcInfo|, it
|
||||
* should just keep the original value unchanged.
|
||||
*/
|
||||
_updateConnectionInfo: function(aDestInfo, aSrcInfo) {
|
||||
let isUpdated = false;
|
||||
for (let key in aSrcInfo) {
|
||||
@ -502,15 +508,13 @@ MobileConnectionProvider.prototype = {
|
||||
} else {
|
||||
aDestInfo.network = this._operatorInfo;
|
||||
|
||||
if (aSrcInfo.cell == null) {
|
||||
if (aDestInfo.cell != null) {
|
||||
isUpdated = true;
|
||||
aDestInfo.cell = null;
|
||||
}
|
||||
} else {
|
||||
if (aDestInfo.cell == null) {
|
||||
// If no new cell data is passed, we should just keep the original cell
|
||||
// data unchanged.
|
||||
if (aSrcInfo.cell) {
|
||||
if (!aDestInfo.cell) {
|
||||
aDestInfo.cell = new MobileCellInfo();
|
||||
}
|
||||
|
||||
isUpdated = this._updateInfo(aDestInfo.cell, aSrcInfo.cell) || isUpdated;
|
||||
}
|
||||
}
|
||||
@ -520,6 +524,12 @@ MobileConnectionProvider.prototype = {
|
||||
return isUpdated;
|
||||
},
|
||||
|
||||
/**
|
||||
* The design of this updating function is to update the attribute in
|
||||
* |aDestInfo| *only if* new data (e.g. aSrcInfo) contains the same attribute.
|
||||
* Thus, for the attribute in |aDestInfo| that isn't showed in |aSrcInfo|, it
|
||||
* should just keep the original value unchanged.
|
||||
*/
|
||||
_updateInfo: function(aDestInfo, aSrcInfo) {
|
||||
let isUpdated = false;
|
||||
for (let key in aSrcInfo) {
|
||||
|
@ -40,13 +40,19 @@ UNIFIED_SOURCES += [
|
||||
'ipc/MobileConnectionParent.cpp',
|
||||
'MobileCallForwardingOptions.cpp',
|
||||
'MobileCellInfo.cpp',
|
||||
'MobileConnection.cpp',
|
||||
'MobileConnectionArray.cpp',
|
||||
'MobileConnectionCallback.cpp',
|
||||
'MobileConnectionInfo.cpp',
|
||||
'MobileNetworkInfo.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'MobileConnection.cpp', # Non-unified due to no_pgo
|
||||
]
|
||||
|
||||
if CONFIG['_MSC_VER'] and CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
SOURCES['MobileConnection.cpp'].no_pgo = True # VS2013 crashes, bug 1084162
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'ipc/PMobileConnection.ipdl',
|
||||
'ipc/PMobileConnectionRequest.ipdl',
|
||||
|
@ -7,7 +7,17 @@ const SETTINGS_KEY_DATA_ENABLED = "ril.data.enabled";
|
||||
const SETTINGS_KEY_DATA_ROAMING_ENABLED = "ril.data.roaming_enabled";
|
||||
const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings";
|
||||
|
||||
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
const PREF_KEY_RIL_DEBUGGING_ENABLED = "ril.debugging.enabled";
|
||||
|
||||
// Emulate Promise.jsm semantics.
|
||||
Promise.defer = function() { return new Deferred(); };
|
||||
function Deferred() {
|
||||
this.promise = new Promise(function(resolve, reject) {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
}.bind(this));
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
let _pendingEmulatorCmdCount = 0;
|
||||
let _pendingEmulatorShellCmdCount = 0;
|
||||
@ -1109,8 +1119,16 @@ function cleanUp() {
|
||||
* A function that takes no parameter.
|
||||
*/
|
||||
function startTestBase(aTestCaseMain) {
|
||||
// Turn on debugging pref.
|
||||
let debugPref = SpecialPowers.getBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED);
|
||||
SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, true);
|
||||
|
||||
Promise.resolve()
|
||||
.then(aTestCaseMain)
|
||||
.then(() => {
|
||||
// Restore debugging pref.
|
||||
SpecialPowers.setBoolPref(PREF_KEY_RIL_DEBUGGING_ENABLED, debugPref);
|
||||
})
|
||||
.then(cleanUp, function() {
|
||||
ok(false, 'promise rejects during test.');
|
||||
cleanUp();
|
||||
|
@ -133,7 +133,7 @@ NfcContentHelper.prototype = {
|
||||
let val = cpmm.sendSyncMessage("NFC:CheckSessionToken", {
|
||||
sessionToken: sessionToken
|
||||
});
|
||||
return (val[0] === NFC.NFC_SUCCESS);
|
||||
return (val[0] === NFC.NFC_GECKO_SUCCESS);
|
||||
},
|
||||
|
||||
// NFCTag interface
|
||||
@ -359,7 +359,12 @@ NfcContentHelper.prototype = {
|
||||
this.eventTarget.notifyPeerLost(result.sessionToken);
|
||||
break;
|
||||
case NFC.TAG_EVENT_FOUND:
|
||||
let event = new NfcTagEvent(result.techList);
|
||||
let event = new NfcTagEvent(result.techList,
|
||||
result.tagType,
|
||||
result.maxNDEFSize,
|
||||
result.isReadOnly,
|
||||
result.isFormatable);
|
||||
|
||||
this.eventTarget.notifyTagFound(result.sessionToken, event, result.records);
|
||||
break;
|
||||
case NFC.TAG_EVENT_LOST:
|
||||
@ -413,13 +418,21 @@ NfcContentHelper.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
function NfcTagEvent(techList) {
|
||||
function NfcTagEvent(techList, tagType, maxNDEFSize, isReadOnly, isFormatable) {
|
||||
this.techList = techList;
|
||||
this.tagType = tagType;
|
||||
this.maxNDEFSize = maxNDEFSize;
|
||||
this.isReadOnly = isReadOnly;
|
||||
this.isFormatable = isFormatable;
|
||||
}
|
||||
NfcTagEvent.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINfcTagEvent]),
|
||||
|
||||
techList: null
|
||||
techList: null,
|
||||
tagType: null,
|
||||
maxNDEFSize: 0,
|
||||
isReadOnly: false,
|
||||
isFormatable: false
|
||||
};
|
||||
|
||||
if (NFC_ENABLED) {
|
||||
|
@ -314,9 +314,9 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
case "NFC:CheckSessionToken":
|
||||
if (!SessionHelper.isValidToken(message.data.sessionToken)) {
|
||||
debug("Received invalid Session Token: " + message.data.sessionToken);
|
||||
return NFC.NFC_ERROR_BAD_SESSION_ID;
|
||||
return NFC.NFC_GECKO_ERROR_BAD_SESSION_ID;
|
||||
}
|
||||
return NFC.NFC_SUCCESS;
|
||||
return NFC.NFC_GECKO_SUCCESS;
|
||||
case "NFC:RegisterPeerReadyTarget":
|
||||
this.registerPeerReadyTarget(message.target, message.data.appId);
|
||||
return null;
|
||||
@ -513,11 +513,6 @@ Nfc.prototype = {
|
||||
let message = Cu.cloneInto(event, this);
|
||||
DEBUG && debug("Received message from NFC Service: " + JSON.stringify(message));
|
||||
|
||||
// mapping error code to error message
|
||||
if (message.status !== undefined && message.status !== NFC.NFC_SUCCESS) {
|
||||
message.errorMsg = this.getErrorMessage(message.status);
|
||||
}
|
||||
|
||||
switch (message.type) {
|
||||
case "InitializedNotification":
|
||||
// Do nothing.
|
||||
@ -561,7 +556,7 @@ Nfc.prototype = {
|
||||
this.notifyHCIEventTransaction(message);
|
||||
break;
|
||||
case "ConfigResponse":
|
||||
if (message.status === NFC.NFC_SUCCESS) {
|
||||
if (!message.errorMsg) {
|
||||
this.powerLevel = message.powerLevel;
|
||||
}
|
||||
|
||||
@ -617,7 +612,7 @@ Nfc.prototype = {
|
||||
// Sanity check on sessionToken.
|
||||
if (!SessionHelper.isValidToken(message.data.sessionToken)) {
|
||||
debug("Invalid Session Token: " + message.data.sessionToken);
|
||||
this.sendNfcErrorResponse(message, NFC.NFC_ERROR_BAD_SESSION_ID);
|
||||
this.sendNfcErrorResponse(message, NFC.NFC_GECKO_ERROR_BAD_SESSION_ID);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
#define NFCD_MAJOR_VERSION 1
|
||||
#define NFCD_MINOR_VERSION 13
|
||||
#define NFCD_MINOR_VERSION 14
|
||||
|
||||
enum NfcRequest {
|
||||
ConfigReq = 0,
|
||||
@ -41,37 +41,24 @@ enum NfcTechlogy {
|
||||
|
||||
enum NfcErrorCode {
|
||||
Success = 0,
|
||||
IOErr = -1,
|
||||
Cancelled = -2,
|
||||
Timeout = -3,
|
||||
BusyErr = -4,
|
||||
ConnectErr = -5,
|
||||
DisconnectErr = -6,
|
||||
ReadErr = -7,
|
||||
WriteErr = -8,
|
||||
InvalidParam = -9,
|
||||
InsufficientResources = -10,
|
||||
SocketCreation = -11,
|
||||
SocketNotConnected = -12,
|
||||
BufferTooSmall = -13,
|
||||
SapUsed = -14,
|
||||
ServiceNameUsed = -15,
|
||||
SocketOptions = -16,
|
||||
FailEnableDiscovery = -17,
|
||||
FailDisableDiscovery = -18,
|
||||
NotInitialized = -19,
|
||||
InitializeFail = -20,
|
||||
DeinitializeFail = -21,
|
||||
SeConnected = -22,
|
||||
NoSeConnected = -23,
|
||||
NotSupported = -24,
|
||||
BadSessionId = -25,
|
||||
LostTech = -26,
|
||||
BadTechType = -27,
|
||||
SelectSeFail = -28,
|
||||
DeselectSeFail = -29,
|
||||
FailEnableLowPowerMode = -30,
|
||||
FailDisableLowPowerMode = -31,
|
||||
IOErr = 1,
|
||||
Timeout = 2,
|
||||
BusyErr = 3,
|
||||
ConnectErr = 4,
|
||||
DisconnectErr = 5,
|
||||
ReadErr = 6,
|
||||
WriteErr = 7,
|
||||
InvalidParam = 8,
|
||||
InsufficientResources = 9,
|
||||
SocketCreation = 10,
|
||||
FailEnableDiscovery = 11,
|
||||
FailDisableDiscovery = 12,
|
||||
NotInitialized = 13,
|
||||
InitializeFail = 14,
|
||||
DeinitializeFail = 15,
|
||||
NotSupported = 16,
|
||||
FailEnableLowPowerMode = 17,
|
||||
FailDisableLowPowerMode = 18,
|
||||
};
|
||||
|
||||
enum SecureElementOrigin {
|
||||
@ -81,15 +68,6 @@ enum SecureElementOrigin {
|
||||
OriginEndGuard = 3
|
||||
};
|
||||
|
||||
enum NdefType {
|
||||
UNKNOWN = -1,
|
||||
TYPE1_TAG = 0,
|
||||
TYPE2_TAG = 1,
|
||||
TYPE3_TAG = 2,
|
||||
TYPE4_TAG = 3,
|
||||
MIFARE_CLASSIC_TAG = 4
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // NfcGonkMessage_h
|
||||
|
@ -129,7 +129,7 @@ NfcMessageHandler::GeneralResponse(const Parcel& aParcel, EventOptions& aOptions
|
||||
}
|
||||
|
||||
aOptions.mType = NS_ConvertUTF8toUTF16(type);
|
||||
aOptions.mStatus = aParcel.readInt32();
|
||||
aOptions.mErrorCode = aParcel.readInt32();
|
||||
aOptions.mSessionId = aParcel.readInt32();
|
||||
|
||||
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
||||
@ -152,8 +152,7 @@ bool
|
||||
NfcMessageHandler::ConfigResponse(const Parcel& aParcel, EventOptions& aOptions)
|
||||
{
|
||||
aOptions.mType = NS_ConvertUTF8toUTF16(kConfigResponse);
|
||||
aOptions.mStatus = aParcel.readInt32();
|
||||
|
||||
aOptions.mErrorCode = aParcel.readInt32();
|
||||
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
||||
aOptions.mRequestId = mRequestIdQueue[0];
|
||||
mRequestIdQueue.RemoveElementAt(0);
|
||||
@ -177,14 +176,14 @@ bool
|
||||
NfcMessageHandler::ReadNDEFResponse(const Parcel& aParcel, EventOptions& aOptions)
|
||||
{
|
||||
aOptions.mType = NS_ConvertUTF8toUTF16(kReadNDEFResponse);
|
||||
aOptions.mStatus = aParcel.readInt32();
|
||||
aOptions.mErrorCode = aParcel.readInt32();
|
||||
aOptions.mSessionId = aParcel.readInt32();
|
||||
|
||||
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
|
||||
aOptions.mRequestId = mRequestIdQueue[0];
|
||||
mRequestIdQueue.RemoveElementAt(0);
|
||||
|
||||
if (aOptions.mStatus == NfcErrorCode::Success) {
|
||||
if (aOptions.mErrorCode == NfcErrorCode::Success) {
|
||||
ReadNDEFMessage(aParcel, aOptions);
|
||||
}
|
||||
|
||||
@ -264,10 +263,10 @@ NfcMessageHandler::TechDiscoveredNotification(const Parcel& aParcel, EventOption
|
||||
|
||||
int32_t ndefInfo = aParcel.readInt32();
|
||||
if (ndefInfo) {
|
||||
NdefType type = static_cast<NdefType>(aParcel.readInt32());
|
||||
int32_t maxSupportLength = aParcel.readInt32();
|
||||
int32_t isReadOnly = aParcel.readInt32();
|
||||
int32_t isFormatable = aParcel.readInt32();
|
||||
aOptions.mTagType = aParcel.readInt32();
|
||||
aOptions.mMaxNDEFSize = aParcel.readInt32();
|
||||
aOptions.mIsReadOnly = aParcel.readInt32();
|
||||
aOptions.mIsFormatable = aParcel.readInt32();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -85,22 +85,25 @@ struct CommandOptions
|
||||
struct EventOptions
|
||||
{
|
||||
EventOptions()
|
||||
: mType(EmptyString()), mStatus(-1), mSessionId(-1), mRequestId(EmptyString()), mMajorVersion(-1), mMinorVersion(-1),
|
||||
mIsReadOnly(-1), mCanBeMadeReadOnly(-1), mMaxSupportedLength(-1), mPowerLevel(-1),
|
||||
: mType(EmptyString()), mStatus(-1), mErrorCode(-1), mSessionId(-1), mRequestId(EmptyString()),
|
||||
mMajorVersion(-1), mMinorVersion(-1),
|
||||
mTagType(-1), mMaxNDEFSize(-1), mIsReadOnly(-1), mIsFormatable(-1), mPowerLevel(-1),
|
||||
mOriginType(-1), mOriginIndex(-1)
|
||||
{}
|
||||
|
||||
nsString mType;
|
||||
int32_t mStatus;
|
||||
int32_t mErrorCode;
|
||||
int32_t mSessionId;
|
||||
nsString mRequestId;
|
||||
int32_t mMajorVersion;
|
||||
int32_t mMinorVersion;
|
||||
nsTArray<uint8_t> mTechList;
|
||||
nsTArray<NDEFRecordStruct> mRecords;
|
||||
int32_t mTagType;
|
||||
int32_t mMaxNDEFSize;
|
||||
int32_t mIsReadOnly;
|
||||
int32_t mCanBeMadeReadOnly;
|
||||
int32_t mMaxSupportedLength;
|
||||
int32_t mIsFormatable;
|
||||
int32_t mPowerLevel;
|
||||
|
||||
int32_t mOriginType;
|
||||
|
@ -106,6 +106,11 @@ public:
|
||||
COPY_OPT_FIELD(mMinorVersion, -1)
|
||||
COPY_OPT_FIELD(mPowerLevel, -1)
|
||||
|
||||
if (mEvent.mErrorCode != -1) {
|
||||
event.mErrorMsg.Construct();
|
||||
event.mErrorMsg.Value() = static_cast<NfcErrorMessage>(mEvent.mErrorCode);
|
||||
}
|
||||
|
||||
if (mEvent.mTechList.Length() > 0) {
|
||||
int length = mEvent.mTechList.Length();
|
||||
event.mTechList.Construct();
|
||||
@ -152,9 +157,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (mEvent.mTagType != -1) {
|
||||
event.mTagType.Construct();
|
||||
event.mTagType.Value() = static_cast<NFCTagType>(mEvent.mTagType);
|
||||
}
|
||||
|
||||
COPY_OPT_FIELD(mMaxNDEFSize, -1)
|
||||
COPY_OPT_FIELD(mIsReadOnly, -1)
|
||||
COPY_OPT_FIELD(mCanBeMadeReadOnly, -1)
|
||||
COPY_OPT_FIELD(mMaxSupportedLength, -1)
|
||||
COPY_OPT_FIELD(mIsFormatable, -1)
|
||||
|
||||
// HCI Event Transaction parameters.
|
||||
if (mEvent.mOriginType != -1) {
|
||||
|
@ -22,58 +22,20 @@ this.DEBUG_ALL = false;
|
||||
this.DEBUG_CONTENT_HELPER = false || DEBUG_ALL;
|
||||
this.DEBUG_NFC = false || DEBUG_ALL;
|
||||
|
||||
// nfcd error codes
|
||||
this.NFC_SUCCESS = 0;
|
||||
this.NFC_ERROR_IO = -1;
|
||||
this.NFC_ERROR_TIMEOUT = -2;
|
||||
this.NFC_ERROR_BUSY = -3;
|
||||
this.NFC_ERROR_CONNECT = -4;
|
||||
this.NFC_ERROR_DISCONNECT = -5;
|
||||
this.NFC_ERROR_READ = -6;
|
||||
this.NFC_ERROR_WRITE = -7;
|
||||
this.NFC_ERROR_INVALID_PARAM = -8;
|
||||
this.NFC_ERROR_INSUFFICIENT_RESOURCES = -9;
|
||||
this.NFC_ERROR_SOCKET_CREATION = -10;
|
||||
this.NFC_ERROR_FAIL_ENABLE_DISCOVERY = -11;
|
||||
this.NFC_ERROR_FAIL_DISABLE_DISCOVERY = -12;
|
||||
this.NFC_ERROR_NOT_INITIALIZED = -13;
|
||||
this.NFC_ERROR_INITIALIZE_FAIL = -14;
|
||||
this.NFC_ERROR_DEINITIALIZE_FAIL = -15;
|
||||
this.NFC_ERROR_NOT_SUPPORTED = -16;
|
||||
this.NFC_ERROR_BAD_SESSION_ID = -17,
|
||||
this.NFC_ERROR_FAIL_ENABLE_LOW_POWER_MODE = -18;
|
||||
this.NFC_ERROR_FAIL_DISABLE_LOW_POWER_MODE = -19;
|
||||
|
||||
// Gecko specific error codes
|
||||
this.NFC_GECKO_SUCCESS = 0;
|
||||
this.NFC_GECKO_ERROR_GENERIC_FAILURE = 1;
|
||||
this.NFC_GECKO_ERROR_P2P_REG_INVALID = 2;
|
||||
this.NFC_GECKO_ERROR_NOT_ENABLED = 3;
|
||||
this.NFC_GECKO_ERROR_SEND_FILE_FAILED = 4;
|
||||
this.NFC_GECKO_ERROR_BAD_SESSION_ID = 5;
|
||||
|
||||
this.NFC_ERROR_MSG = {};
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_IO] = "NfcIoError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_TIMEOUT] = "NfcTimeoutError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_BUSY] = "NfcBusyError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_CONNECT] = "NfcConnectError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_DISCONNECT] = "NfcDisconnectError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_READ] = "NfcReadError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_WRITE] = "NfcWriteError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_INVALID_PARAM] = "NfcInvalidParamError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_INSUFFICIENT_RESOURCES] = "NfcInsufficentResourcesError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_SOCKET_CREATION] = "NfcSocketCreationError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_FAIL_ENABLE_DISCOVERY] = "NfcFailEnableDiscoveryError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_FAIL_DISABLE_DISCOVERY] = "NfcFailDisableDiscoveryError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_NOT_INITIALIZED] = "NfcNotInitializedError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_INITIALIZE_FAIL] = "NfcInitializeFailError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_DEINITIALIZE_FAIL] = "NfcDeinitializeFailError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_NOT_SUPPORTED] = "NfcNotSupportedError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_BAD_SESSION_ID] = "NfcBadSessionIdError";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_FAIL_ENABLE_LOW_POWER_MODE] = "EnableLowPowerModeFail";
|
||||
this.NFC_ERROR_MSG[this.NFC_ERROR_FAIL_DISABLE_LOW_POWER_MODE] = "DisableLowPowerModeFail";
|
||||
this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_GENERIC_FAILURE] = "NfcGenericFailureError";
|
||||
this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_P2P_REG_INVALID] = "NfcP2PRegistrationInvalid";
|
||||
this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_NOT_ENABLED] = "NfcNotEnabledError";
|
||||
this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_SEND_FILE_FAILED] = "NfcSendFileFailed";
|
||||
this.NFC_ERROR_MSG[this.NFC_GECKO_ERROR_BAD_SESSION_ID] = "NfcBadSessionID";
|
||||
|
||||
// NFC powerlevels must match config PDUs.
|
||||
this.NFC_POWER_LEVEL_UNKNOWN = -1;
|
||||
|
@ -34,43 +34,46 @@ HCIEventTransactionSystemMessageConfigurator.prototype = {
|
||||
},
|
||||
|
||||
shouldDispatch: function shouldDispatch(aManifestURL, aPageURL, aType, aMessage, aExtra) {
|
||||
let deferred = Promise.defer();
|
||||
debug("message to dispatch: " + JSON.stringify(aMessage));
|
||||
DEBUG && debug("message to dispatch: " + JSON.stringify(aMessage));
|
||||
debug("aManifest url: " + aManifestURL);
|
||||
if(!aMessage) {
|
||||
return deferred.resolve(false);
|
||||
|
||||
if (!aMessage) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
let aid = this._byteAIDToHex(aMessage.aid);
|
||||
let seName = aMessage.seName;
|
||||
|
||||
appsService.getManifestFor(aManifestURL)
|
||||
.then((aManifest) => this._checkAppManifest(seName, aid, aManifest))
|
||||
.then(() => {
|
||||
// FIXME: Bug 884594: Access Control Enforcer
|
||||
// Here we will call ace.isAllowed function which will also return
|
||||
// a Promise, for now we're just resolving shouldDispatch promise
|
||||
debug("dispatching message");
|
||||
deferred.resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
// if the Promise chain was broken we don't dispatch the message
|
||||
debug("not dispatching");
|
||||
deferred.resolve(false);
|
||||
return new Promise((resolve, reject) => {
|
||||
appsService.getManifestFor(aManifestURL)
|
||||
.then((aManifest) => this._checkAppManifest(aMessage.origin, aMessage.aid, aManifest))
|
||||
.then(() => {
|
||||
// FIXME: Bug 884594: Access Control Enforcer
|
||||
// Here we will call ace.isAllowed function which will also return
|
||||
// a Promise, for now we're just resolving shouldDispatch promise
|
||||
debug("dispatching message");
|
||||
resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
// if the Promise chain was broken we don't dispatch the message
|
||||
debug("not dispatching");
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
// we might be doing some async hash computations here, returning
|
||||
// a resolved/rejected promise for now so we can easily fit the method
|
||||
// into a Promise chain
|
||||
_checkAppManifest: function _checkAppManifest(aSeName, aAid, aManifest) {
|
||||
debug("aManifest " + JSON.stringify(aManifest));
|
||||
_checkAppManifest: function _checkAppManifest(aOrigin, aAid, aManifest) {
|
||||
DEBUG && debug("aManifest " + JSON.stringify(aManifest));
|
||||
|
||||
// convert AID and Secure Element name to uppercased string for comparison
|
||||
// with manifest secure_element_access rules
|
||||
let aid = this._byteAIDToHex(aAid);
|
||||
let seName = (aOrigin) ? aOrigin.toUpperCase() : "";
|
||||
|
||||
let hciRules = aManifest["secure_element_access"] || [];
|
||||
let matchingRule = hciRules.find((rule) => {
|
||||
rule = rule.toUpperCase();
|
||||
if(rule === "*" || rule === (aSeName + "/" + aAid)) {
|
||||
if(rule === "*" || rule === (seName + "/" + aid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -85,8 +88,8 @@ HCIEventTransactionSystemMessageConfigurator.prototype = {
|
||||
return match === element;
|
||||
};
|
||||
|
||||
return isMatching(rule.split('/')[0], aSeName) &&
|
||||
isMatching(rule.split('/')[1], aAid);
|
||||
return isMatching(rule.split('/')[0], seName) &&
|
||||
isMatching(rule.split('/')[1], aid);
|
||||
});
|
||||
|
||||
return (matchingRule) ? Promise.resolve() : Promise.reject();
|
||||
|
@ -40,6 +40,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_NFC']:
|
||||
EXTRA_JS_MODULES += [
|
||||
'gonk/nfc_consts.js',
|
||||
]
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/unit/xpcshell.ini'
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
@ -7,10 +7,19 @@
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(44eb02f4-6eba-4c12-8ed1-c142513776c9)]
|
||||
[scriptable, uuid(9b43bdda-52f4-4712-b28c-ad7cba736e14)]
|
||||
interface nsINfcTagEvent : nsISupports
|
||||
{
|
||||
readonly attribute nsIVariant techList;
|
||||
|
||||
// one of NFCTagType defined in MozNFCTag.webidl.
|
||||
readonly attribute DOMString tagType;
|
||||
|
||||
readonly attribute long maxNDEFSize;
|
||||
|
||||
readonly attribute boolean isReadOnly;
|
||||
|
||||
readonly attribute boolean isFormatable;
|
||||
};
|
||||
|
||||
[scriptable, uuid(2074503e-f590-4017-a45e-85d3ca766f41)]
|
||||
|
@ -24,18 +24,38 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"nsIAppsService");
|
||||
|
||||
/**
|
||||
* NFCTag
|
||||
* Implementation of NFCTag.
|
||||
*
|
||||
* @param window global window object.
|
||||
* @param sessionToken session token received from parent process.
|
||||
* @parem event type of nsINfcTagEvent received from parent process.
|
||||
*/
|
||||
function MozNFCTag(aWindow, aSessionToken) {
|
||||
debug("In MozNFCTag Constructor");
|
||||
function MozNFCTagImpl(window, sessionToken, event) {
|
||||
debug("In MozNFCTagImpl Constructor");
|
||||
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
||||
.getService(Ci.nsINfcContentHelper);
|
||||
this._window = aWindow;
|
||||
this.session = aSessionToken;
|
||||
this._window = window;
|
||||
this.session = sessionToken;
|
||||
this.techList = event.techList;
|
||||
this.type = event.tagType || null;
|
||||
this.maxNDEFSize = event.maxNDEFSize || null;
|
||||
this.isReadOnly = event.isReadOnly || null;
|
||||
this.isFormatable = event.isFormatable || null;
|
||||
this.canBeMadeReadOnly = this.type ?
|
||||
(this.type == "type1" || this.type == "type2" ||
|
||||
this.type == "mifare_classic") :
|
||||
null;
|
||||
}
|
||||
MozNFCTag.prototype = {
|
||||
MozNFCTagImpl.prototype = {
|
||||
_nfcContentHelper: null,
|
||||
_window: null,
|
||||
session: null,
|
||||
techList: null,
|
||||
type: null,
|
||||
maxNDEFSize: 0,
|
||||
isReadOnly: false,
|
||||
isFormatable: false,
|
||||
canBeMadeReadOnly: false,
|
||||
|
||||
// NFCTag interface:
|
||||
readNDEF: function readNDEF() {
|
||||
@ -55,17 +75,20 @@ MozNFCTag.prototype = {
|
||||
};
|
||||
|
||||
/**
|
||||
* NFCPeer
|
||||
* Implementation of NFCPeer.
|
||||
*
|
||||
* @param window global window object.
|
||||
* @param sessionToken session token received from parent process.
|
||||
*/
|
||||
function MozNFCPeer(aWindow, aSessionToken) {
|
||||
debug("In MozNFCPeer Constructor");
|
||||
function MozNFCPeerImpl(aWindow, aSessionToken) {
|
||||
debug("In MozNFCPeerImpl Constructor");
|
||||
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
||||
.getService(Ci.nsINfcContentHelper);
|
||||
|
||||
this._window = aWindow;
|
||||
this.session = aSessionToken;
|
||||
}
|
||||
MozNFCPeer.prototype = {
|
||||
MozNFCPeerImpl.prototype = {
|
||||
_nfcContentHelper: null,
|
||||
_window: null,
|
||||
_isLost: false,
|
||||
@ -103,10 +126,10 @@ MozNFCPeer.prototype = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigator NFC object
|
||||
* Implementation of navigator NFC object.
|
||||
*/
|
||||
function mozNfc() {
|
||||
debug("In mozNfc Constructor");
|
||||
function MozNFCImpl() {
|
||||
debug("In MozNFCImpl Constructor");
|
||||
try {
|
||||
this._nfcContentHelper = Cc["@mozilla.org/nfc/content-helper;1"]
|
||||
.getService(Ci.nsINfcContentHelper);
|
||||
@ -116,13 +139,13 @@ function mozNfc() {
|
||||
|
||||
this._nfcContentHelper.registerEventTarget(this);
|
||||
}
|
||||
mozNfc.prototype = {
|
||||
MozNFCImpl.prototype = {
|
||||
_nfcContentHelper: null,
|
||||
_window: null,
|
||||
nfcObject: null,
|
||||
|
||||
init: function init(aWindow) {
|
||||
debug("mozNfc init called");
|
||||
debug("MozNFCImpl init called");
|
||||
this._window = aWindow;
|
||||
this.defineEventHandlerGetterSetter("ontagfound");
|
||||
this.defineEventHandlerGetterSetter("ontaglost");
|
||||
@ -172,7 +195,7 @@ mozNfc.prototype = {
|
||||
}
|
||||
|
||||
if (!this.nfcObject || this.nfcObject.session != sessionToken) {
|
||||
let obj = new MozNFCPeer(this._window, sessionToken);
|
||||
let obj = new MozNFCPeerImpl(this._window, sessionToken);
|
||||
this.nfcObject = obj;
|
||||
this.nfcObject.contentObject = this._window.MozNFCPeer._create(this._window, obj);
|
||||
}
|
||||
@ -219,8 +242,8 @@ mozNfc.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let tag = new MozNFCTag(this._window, sessionToken);
|
||||
let tagContentObj = this._window.MozNFCTag._create(this._window, tag);
|
||||
let tagImpl = new MozNFCTagImpl(this._window, sessionToken, event);
|
||||
let tag = this._window.MozNFCTag._create(this._window, tagImpl);
|
||||
|
||||
let length = records ? records.length : 0;
|
||||
let ndefRecords = records ? [] : null;
|
||||
@ -233,7 +256,7 @@ mozNfc.prototype = {
|
||||
}
|
||||
|
||||
let eventData = {
|
||||
"tag": tagContentObj,
|
||||
"tag": tag,
|
||||
"ndefRecords": ndefRecords
|
||||
};
|
||||
|
||||
@ -329,4 +352,5 @@ mozNfc.prototype = {
|
||||
Ci.nsINfcDOMEventTarget]),
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozNFCTag, MozNFCPeer, mozNfc]);
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozNFCTagImpl,
|
||||
MozNFCPeerImpl, MozNFCImpl]);
|
||||
|
@ -0,0 +1,98 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* globals run_next_test, add_test, ok, equal, Components, XPCOMUtils */
|
||||
/* exported run_test */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const MANIFEST_URL = "app://system.gaiamobile.org/manifest.webapp";
|
||||
// secure element access rule format: <secure element name>/<hex string aid>
|
||||
const MANIFEST = {
|
||||
secure_element_access: [
|
||||
// rule0, full AID, SIM1 Secure Element
|
||||
"SIM1/000102030405060708090A0B0C0D0E",
|
||||
// rule1, every AID from embedded Secure Element
|
||||
"eSE/*",
|
||||
// rule2, every AID which starts with 0xA0, from every Secure Element
|
||||
"*/a0*"
|
||||
]
|
||||
};
|
||||
const PAGE_URL = "app://system.gaiamobile.org/index.html";
|
||||
const TYPE = "nfc-hci-event-transaction";
|
||||
|
||||
// dummy messages for testing with additional test property - |expectedResult|
|
||||
const TEST_MESSAGES = [
|
||||
{ origin: "SIM1", expectedResult: false },
|
||||
{ aid: new Uint8Array([0xA0]), expectedResult: true },
|
||||
{ aid: new Uint8Array([0xDF]), origin: "eSE", expectedResult: true },
|
||||
{ aid: new Uint8Array([0xA0, 0x01, 0x02, 0x03]), origin: "SIM2", expectedResult: true },
|
||||
{ aid: new Uint8Array([0x02]), origin: "SIM3", expectedResult: false },
|
||||
{ aid: new Uint8Array([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E]),
|
||||
origin: "SIM1", expectedResult: true }
|
||||
];
|
||||
|
||||
let HCIEvtTransactionConfigurator = null;
|
||||
|
||||
function setMockAppService(manifest) {
|
||||
XPCOMUtils.defineLazyServiceGetter = (obj) => {
|
||||
obj.appsService = {
|
||||
getManifestFor: (manifestURL) => {
|
||||
equal(manifestURL, MANIFEST_URL, "should pass proper manifestUrl");
|
||||
return Promise.resolve(manifest);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function getSystemMessageConfigurator() {
|
||||
return Cc[
|
||||
"@mozilla.org/dom/system-messages/configurator/nfc-hci-event-transaction;1"
|
||||
].createInstance(Ci.nsISystemMessagesConfigurator);
|
||||
}
|
||||
|
||||
function handleRejectedPromise() {
|
||||
ok(false, "Promise should not be rejected");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
setMockAppService(MANIFEST);
|
||||
HCIEvtTransactionConfigurator = getSystemMessageConfigurator();
|
||||
|
||||
ok(!!HCIEvtTransactionConfigurator, "Configurator should be instantiated");
|
||||
ok((typeof HCIEvtTransactionConfigurator.shouldDispatch) === "function",
|
||||
"shouldDispatch should be a function");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_shouldDispatch_no_message() {
|
||||
HCIEvtTransactionConfigurator
|
||||
.shouldDispatch(MANIFEST_URL, PAGE_URL, TYPE, null)
|
||||
.then((result) => {
|
||||
ok(!result, "Should be false without message");
|
||||
})
|
||||
.catch(handleRejectedPromise)
|
||||
.then(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_shouldDispatch_general_rule_validation() {
|
||||
let promises = TEST_MESSAGES.map((m) => {
|
||||
return HCIEvtTransactionConfigurator
|
||||
.shouldDispatch(MANIFEST_URL, PAGE_URL, TYPE, m);
|
||||
});
|
||||
|
||||
Promise.all(promises).then((results) => {
|
||||
results.forEach((result, idx) => {
|
||||
ok(result === TEST_MESSAGES[idx].expectedResult, "tested message: " + JSON.stringify(TEST_MESSAGES[idx]));
|
||||
});
|
||||
})
|
||||
.catch(handleRejectedPromise)
|
||||
.then(run_next_test);
|
||||
});
|
5
dom/nfc/tests/unit/xpcshell.ini
Normal file
5
dom/nfc/tests/unit/xpcshell.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_HCIEventTransactionSystemMessageConfigurator.js]
|
@ -2368,6 +2368,13 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
|
||||
for (size_t i = 0; i < plugins.Length(); i++) {
|
||||
nsRefPtr<nsPluginTag> tag = plugins[i];
|
||||
|
||||
if (!nsNPAPIPlugin::RunPluginOOP(tag)) {
|
||||
// Don't expose non-OOP plugins to content processes since we have no way
|
||||
// to bridge them over.
|
||||
continue;
|
||||
}
|
||||
|
||||
aPlugins->AppendElement(PluginTag(tag->mId,
|
||||
tag->mName,
|
||||
tag->mDescription,
|
||||
|
@ -29,8 +29,9 @@ public:
|
||||
AddPattern(const nsACString& aPattern)
|
||||
{
|
||||
MOZ_ASSERT(!mOrigins.Count());
|
||||
MOZ_ASSERT(!ContainsPattern(aPattern));
|
||||
mPatterns.AppendElement(aPattern);
|
||||
if (!ContainsPattern(aPattern)) {
|
||||
mPatterns.AppendElement(aPattern);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -48,8 +49,9 @@ public:
|
||||
void
|
||||
AddOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
MOZ_ASSERT(!ContainsOrigin(aOrigin));
|
||||
mOrigins.PutEntry(aOrigin);
|
||||
if (!ContainsOrigin(aOrigin)) {
|
||||
mOrigins.PutEntry(aOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -82,14 +82,24 @@ PersistenceTypeToStorage(PersistenceType aPersistenceType)
|
||||
}
|
||||
|
||||
inline PersistenceType
|
||||
PersistenceTypeFromStorage(const Optional<mozilla::dom::StorageType>& aStorage,
|
||||
PersistenceType aDefaultPersistenceType)
|
||||
PersistenceTypeFromStorage(const Optional<mozilla::dom::StorageType>& aStorage)
|
||||
{
|
||||
if (aStorage.WasPassed()) {
|
||||
return PersistenceType(static_cast<int>(aStorage.Value()));
|
||||
}
|
||||
|
||||
return aDefaultPersistenceType;
|
||||
return PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
|
||||
inline PersistenceType
|
||||
ComplementaryPersistenceType(PersistenceType aPersistenceType)
|
||||
{
|
||||
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
|
||||
return PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY);
|
||||
return PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,6 @@
|
||||
#include "ArrayCluster.h"
|
||||
#include "Client.h"
|
||||
#include "PersistenceType.h"
|
||||
#include "StoragePrivilege.h"
|
||||
|
||||
#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
|
||||
|
||||
@ -55,6 +54,18 @@ class QuotaObject;
|
||||
class ResetOrClearRunnable;
|
||||
struct SynchronizedOp;
|
||||
|
||||
struct OriginParams
|
||||
{
|
||||
OriginParams(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin)
|
||||
: mOrigin(aOrigin)
|
||||
, mPersistenceType(aPersistenceType)
|
||||
{ }
|
||||
|
||||
nsCString mOrigin;
|
||||
PersistenceType mPersistenceType;
|
||||
};
|
||||
|
||||
class QuotaManager MOZ_FINAL : public nsIQuotaManager,
|
||||
public nsIObserver
|
||||
{
|
||||
@ -79,6 +90,9 @@ class QuotaManager MOZ_FINAL : public nsIQuotaManager,
|
||||
typedef void
|
||||
(*WaitingOnStoragesCallback)(nsTArray<nsCOMPtr<nsIOfflineStorage> >&, void*);
|
||||
|
||||
typedef nsClassHashtable<nsCStringHashKey,
|
||||
nsTArray<nsIOfflineStorage*>> LiveStorageTable;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIQUOTAMANAGER
|
||||
@ -103,6 +117,7 @@ public:
|
||||
InitQuotaForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
bool aIsApp,
|
||||
uint64_t aLimitBytes,
|
||||
uint64_t aUsageBytes,
|
||||
int64_t aAccessTime);
|
||||
@ -122,7 +137,7 @@ public:
|
||||
RemoveQuota();
|
||||
|
||||
void
|
||||
RemoveQuotaForPersistenceType(PersistenceType);
|
||||
RemoveQuotaForTemporaryStorage();
|
||||
|
||||
void
|
||||
RemoveQuotaForOrigin(PersistenceType aPersistenceType,
|
||||
@ -253,7 +268,8 @@ public:
|
||||
EnsureOriginIsInitialized(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
bool aTrackQuota,
|
||||
bool aIsApp,
|
||||
bool aHasUnlimStoragePerm,
|
||||
nsIFile** aDirectory);
|
||||
|
||||
void
|
||||
@ -314,30 +330,52 @@ public:
|
||||
GetInfoFromURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
PersistenceType aPersistenceType,
|
||||
nsACString* aGroup,
|
||||
nsACString* aOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
bool* aIsApp,
|
||||
bool* aHasUnlimStoragePerm);
|
||||
|
||||
static nsresult
|
||||
GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
PersistenceType aPersistenceType,
|
||||
nsACString* aGroup,
|
||||
nsACString* aOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
bool* aIsApp,
|
||||
bool* aHasUnlimStoragePerm);
|
||||
|
||||
static nsresult
|
||||
GetInfoFromWindow(nsPIDOMWindow* aWindow,
|
||||
PersistenceType aPersistenceType,
|
||||
nsACString* aGroup,
|
||||
nsACString* aOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
bool* aIsApp,
|
||||
bool* aHasUnlimStoragePerm);
|
||||
|
||||
static void
|
||||
GetInfoForChrome(nsACString* aGroup,
|
||||
nsACString* aOrigin,
|
||||
StoragePrivilege* aPrivilege,
|
||||
PersistenceType* aDefaultPersistenceType);
|
||||
bool* aIsApp,
|
||||
bool* aHasUnlimStoragePerm);
|
||||
|
||||
static bool
|
||||
IsTreatedAsPersistent(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
bool aIsApp);
|
||||
|
||||
static bool
|
||||
IsTreatedAsTemporary(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
bool aIsApp)
|
||||
{
|
||||
return !IsTreatedAsPersistent(aPersistenceType, aOrigin, aIsApp);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsQuotaEnforced(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
bool aIsApp,
|
||||
bool aHasUnlimStoragePerm);
|
||||
|
||||
static void
|
||||
ChromeOrigin(nsACString& aOrigin);
|
||||
@ -412,11 +450,15 @@ private:
|
||||
nsresult
|
||||
MaybeUpgradeIndexedDBDirectory();
|
||||
|
||||
nsresult
|
||||
InitializeRepository(PersistenceType aPersistenceType);
|
||||
|
||||
nsresult
|
||||
InitializeOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
bool aTrackQuota,
|
||||
bool aIsApp,
|
||||
bool aHasUnlimStoragePerm,
|
||||
int64_t aAccessTime,
|
||||
nsIFile* aDirectory);
|
||||
|
||||
@ -432,13 +474,16 @@ private:
|
||||
nsTArray<OriginInfo*>& aOriginInfos);
|
||||
|
||||
void
|
||||
DeleteTemporaryFilesForOrigin(const nsACString& aOrigin);
|
||||
DeleteFilesForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
void
|
||||
FinalizeOriginEviction(nsTArray<nsCString>& aOrigins);
|
||||
FinalizeOriginEviction(nsTArray<OriginParams>& aOrigins);
|
||||
|
||||
void
|
||||
SaveOriginAccessTime(const nsACString& aOrigin, int64_t aTimestamp);
|
||||
SaveOriginAccessTime(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin,
|
||||
int64_t aTimestamp);
|
||||
|
||||
void
|
||||
ReleaseIOThreadObjects()
|
||||
@ -454,6 +499,9 @@ private:
|
||||
void
|
||||
AbortCloseStoragesFor(OwnerClass* aOwnerClass);
|
||||
|
||||
LiveStorageTable&
|
||||
GetLiveStorageTable(PersistenceType aPersistenceType);
|
||||
|
||||
static void
|
||||
GetOriginPatternString(uint32_t aAppId,
|
||||
MozBrowserPatternFlag aBrowserFlag,
|
||||
@ -461,9 +509,9 @@ private:
|
||||
nsAutoCString& _retval);
|
||||
|
||||
static PLDHashOperator
|
||||
RemoveQuotaForPersistenceTypeCallback(const nsACString& aKey,
|
||||
nsAutoPtr<GroupInfoPair>& aValue,
|
||||
void* aUserArg);
|
||||
RemoveQuotaForTemporaryStorageCallback(const nsACString& aKey,
|
||||
nsAutoPtr<GroupInfoPair>& aValue,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator
|
||||
RemoveQuotaCallback(const nsACString& aKey,
|
||||
@ -486,9 +534,9 @@ private:
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator
|
||||
AddTemporaryStorageOrigins(const nsACString& aKey,
|
||||
ArrayCluster<nsIOfflineStorage*>* aValue,
|
||||
void* aUserArg);
|
||||
AddLiveStorageOrigins(const nsACString& aKey,
|
||||
nsTArray<nsIOfflineStorage*>* aValue,
|
||||
void* aUserArg);
|
||||
|
||||
static PLDHashOperator
|
||||
GetInactiveTemporaryStorageOrigins(const nsACString& aKey,
|
||||
@ -510,6 +558,9 @@ private:
|
||||
nsClassHashtable<nsCStringHashKey,
|
||||
ArrayCluster<nsIOfflineStorage*> > mLiveStorages;
|
||||
|
||||
LiveStorageTable mPersistentLiveStorageTable;
|
||||
LiveStorageTable mTemporaryLiveStorageTable;
|
||||
|
||||
// Maintains a list of synchronized operatons that are in progress or queued.
|
||||
nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps;
|
||||
|
||||
|
@ -75,7 +75,7 @@ QuotaObject::UpdateSize(int64_t aSize)
|
||||
|
||||
GroupInfo* groupInfo = mOriginInfo->mGroupInfo;
|
||||
|
||||
if (groupInfo->IsForTemporaryStorage()) {
|
||||
if (mOriginInfo->IsTreatedAsTemporary()) {
|
||||
quotaManager->mTemporaryStorageUsage -= mSize;
|
||||
}
|
||||
groupInfo->mUsage -= mSize;
|
||||
@ -85,7 +85,7 @@ QuotaObject::UpdateSize(int64_t aSize)
|
||||
|
||||
mOriginInfo->mUsage += mSize;
|
||||
groupInfo->mUsage += mSize;
|
||||
if (groupInfo->IsForTemporaryStorage()) {
|
||||
if (mOriginInfo->IsTreatedAsTemporary()) {
|
||||
quotaManager->mTemporaryStorageUsage += mSize;
|
||||
}
|
||||
}
|
||||
@ -106,7 +106,7 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
|
||||
GroupInfo* groupInfo = mOriginInfo->mGroupInfo;
|
||||
|
||||
if (groupInfo->IsForPersistentStorage()) {
|
||||
if (mOriginInfo->IsTreatedAsPersistent()) {
|
||||
uint64_t newUsage = mOriginInfo->mUsage - mSize + end;
|
||||
|
||||
if (newUsage > mOriginInfo->mLimit) {
|
||||
@ -135,7 +135,7 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
NS_ASSERTION(!mOriginInfo,
|
||||
"Should have cleared in LockedClearOriginInfos!");
|
||||
|
||||
quotaManager->LockedRemoveQuotaForOrigin(PERSISTENCE_TYPE_PERSISTENT,
|
||||
quotaManager->LockedRemoveQuotaForOrigin(groupInfo->mPersistenceType,
|
||||
group, origin);
|
||||
|
||||
// Some other thread could increase the size without blocking (increasing
|
||||
@ -156,8 +156,9 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(groupInfo->mPersistenceType == PERSISTENCE_TYPE_TEMPORARY,
|
||||
"Huh?");
|
||||
nsRefPtr<GroupInfo> complementaryGroupInfo =
|
||||
groupInfo->mGroupInfoPair->LockedGetGroupInfo(
|
||||
ComplementaryPersistenceType(groupInfo->mPersistenceType));
|
||||
|
||||
uint64_t delta = end - mSize;
|
||||
|
||||
@ -168,9 +169,14 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
|
||||
uint64_t newGroupUsage = groupInfo->mUsage + delta;
|
||||
|
||||
uint64_t groupUsage = groupInfo->LockedGetTemporaryUsage();
|
||||
if (complementaryGroupInfo) {
|
||||
groupUsage += complementaryGroupInfo->LockedGetTemporaryUsage();
|
||||
}
|
||||
|
||||
// Temporary storage has a hard limit for group usage (20 % of the global
|
||||
// limit).
|
||||
if (newGroupUsage > quotaManager->GetGroupLimit()) {
|
||||
if (groupUsage + delta > quotaManager->GetGroupLimit()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -194,7 +200,11 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);
|
||||
|
||||
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||
quotaManager->DeleteTemporaryFilesForOrigin(originInfos[i]->mOrigin);
|
||||
OriginInfo* originInfo = originInfos[i];
|
||||
|
||||
quotaManager->DeleteFilesForOrigin(
|
||||
originInfo->mGroupInfo->mPersistenceType,
|
||||
originInfo->mOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,22 +212,23 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
|
||||
NS_ASSERTION(mOriginInfo, "How come?!");
|
||||
|
||||
nsTArray<nsCString> origins;
|
||||
nsTArray<OriginParams> origins;
|
||||
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||
OriginInfo* originInfo = originInfos[i];
|
||||
|
||||
NS_ASSERTION(originInfo != mOriginInfo, "Deleted itself!");
|
||||
|
||||
PersistenceType persistenceType =
|
||||
originInfo->mGroupInfo->mPersistenceType;
|
||||
nsCString group = originInfo->mGroupInfo->mGroup;
|
||||
nsCString origin = originInfo->mOrigin;
|
||||
quotaManager->LockedRemoveQuotaForOrigin(PERSISTENCE_TYPE_TEMPORARY,
|
||||
group, origin);
|
||||
quotaManager->LockedRemoveQuotaForOrigin(persistenceType, group, origin);
|
||||
|
||||
#ifdef DEBUG
|
||||
originInfos[i] = nullptr;
|
||||
#endif
|
||||
|
||||
origins.AppendElement(origin);
|
||||
origins.AppendElement(OriginParams(persistenceType, origin));
|
||||
}
|
||||
|
||||
// We unlocked and relocked several times so we need to recompute all the
|
||||
@ -229,7 +240,12 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
|
||||
newGroupUsage = groupInfo->mUsage + delta;
|
||||
|
||||
if (newGroupUsage > quotaManager->GetGroupLimit()) {
|
||||
groupUsage = groupInfo->LockedGetTemporaryUsage();
|
||||
if (complementaryGroupInfo) {
|
||||
groupUsage += complementaryGroupInfo->LockedGetTemporaryUsage();
|
||||
}
|
||||
|
||||
if (groupUsage + delta > quotaManager->GetGroupLimit()) {
|
||||
// Unfortunately some other thread increased the group usage in the
|
||||
// meantime and we are not below the group limit anymore.
|
||||
|
||||
@ -276,6 +292,20 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginInfo::IsTreatedAsPersistent() const
|
||||
{
|
||||
return QuotaManager::IsTreatedAsPersistent(mGroupInfo->mPersistenceType,
|
||||
mOrigin, mIsApp);
|
||||
}
|
||||
|
||||
bool
|
||||
OriginInfo::IsTreatedAsTemporary() const
|
||||
{
|
||||
return QuotaManager::IsTreatedAsTemporary(mGroupInfo->mPersistenceType,
|
||||
mOrigin, mIsApp);
|
||||
}
|
||||
|
||||
void
|
||||
OriginInfo::LockedDecreaseUsage(int64_t aSize)
|
||||
{
|
||||
@ -285,7 +315,7 @@ OriginInfo::LockedDecreaseUsage(int64_t aSize)
|
||||
|
||||
mGroupInfo->mUsage -= aSize;
|
||||
|
||||
if (mGroupInfo->IsForTemporaryStorage()) {
|
||||
if (IsTreatedAsTemporary()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
@ -335,7 +365,7 @@ GroupInfo::LockedAddOriginInfo(OriginInfo* aOriginInfo)
|
||||
|
||||
mUsage += aOriginInfo->mUsage;
|
||||
|
||||
if (IsForTemporaryStorage()) {
|
||||
if (aOriginInfo->IsTreatedAsTemporary()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
@ -352,7 +382,7 @@ GroupInfo::LockedRemoveOriginInfo(const nsACString& aOrigin)
|
||||
if (mOriginInfos[index]->mOrigin == aOrigin) {
|
||||
mUsage -= mOriginInfos[index]->mUsage;
|
||||
|
||||
if (IsForTemporaryStorage()) {
|
||||
if (mOriginInfos[index]->IsTreatedAsTemporary()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
@ -372,13 +402,15 @@ GroupInfo::LockedRemoveOriginInfos()
|
||||
AssertCurrentThreadOwnsQuotaMutex();
|
||||
|
||||
for (uint32_t index = mOriginInfos.Length(); index > 0; index--) {
|
||||
mUsage -= mOriginInfos[index - 1]->mUsage;
|
||||
OriginInfo* originInfo = mOriginInfos[index - 1];
|
||||
|
||||
if (IsForTemporaryStorage()) {
|
||||
mUsage -= originInfo->mUsage;
|
||||
|
||||
if (originInfo->IsTreatedAsTemporary()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
quotaManager->mTemporaryStorageUsage -= mOriginInfos[index - 1]->mUsage;
|
||||
quotaManager->mTemporaryStorageUsage -= originInfo->mUsage;
|
||||
}
|
||||
|
||||
mOriginInfos.RemoveElementAt(index - 1);
|
||||
@ -394,7 +426,7 @@ GroupInfo::LockedRemoveOriginInfosForPattern(const nsACString& aPattern)
|
||||
if (PatternMatchesOrigin(aPattern, mOriginInfos[index - 1]->mOrigin)) {
|
||||
mUsage -= mOriginInfos[index - 1]->mUsage;
|
||||
|
||||
if (IsForTemporaryStorage()) {
|
||||
if (mOriginInfos[index - 1]->IsTreatedAsTemporary()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
@ -406,6 +438,62 @@ GroupInfo::LockedRemoveOriginInfosForPattern(const nsACString& aPattern)
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
GroupInfo::LockedGetTemporaryUsage()
|
||||
{
|
||||
uint64_t usage = 0;
|
||||
|
||||
for (uint32_t count = mOriginInfos.Length(), index = 0;
|
||||
index < count;
|
||||
index++) {
|
||||
nsRefPtr<OriginInfo>& originInfo = mOriginInfos[index];
|
||||
|
||||
if (originInfo->IsTreatedAsTemporary()) {
|
||||
usage += originInfo->mUsage;
|
||||
}
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
void
|
||||
GroupInfo::LockedGetTemporaryOriginInfos(nsTArray<OriginInfo*>* aOriginInfos)
|
||||
{
|
||||
AssertCurrentThreadOwnsQuotaMutex();
|
||||
|
||||
for (uint32_t count = mOriginInfos.Length(), index = 0;
|
||||
index < count;
|
||||
index++) {
|
||||
nsRefPtr<OriginInfo>& originInfo = mOriginInfos[index];
|
||||
|
||||
if (originInfo->IsTreatedAsTemporary()) {
|
||||
aOriginInfos->AppendElement(originInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GroupInfo::LockedRemoveTemporaryOriginInfos()
|
||||
{
|
||||
AssertCurrentThreadOwnsQuotaMutex();
|
||||
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager);
|
||||
|
||||
for (uint32_t index = mOriginInfos.Length(); index > 0; index--) {
|
||||
OriginInfo* originInfo = mOriginInfos[index - 1];
|
||||
if (originInfo->IsTreatedAsTemporary()) {
|
||||
MOZ_ASSERT(mUsage >= originInfo->mUsage);
|
||||
mUsage -= originInfo->mUsage;
|
||||
|
||||
MOZ_ASSERT(quotaManager->mTemporaryStorageUsage >= originInfo->mUsage);
|
||||
quotaManager->mTemporaryStorageUsage -= originInfo->mUsage;
|
||||
|
||||
mOriginInfos.RemoveElementAt(index - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<GroupInfo>&
|
||||
GroupInfoPair::GetGroupInfoForPersistenceType(PersistenceType aPersistenceType)
|
||||
{
|
||||
|
@ -75,10 +75,10 @@ class OriginInfo MOZ_FINAL
|
||||
friend class QuotaObject;
|
||||
|
||||
public:
|
||||
OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin, uint64_t aLimit,
|
||||
uint64_t aUsage, int64_t aAccessTime)
|
||||
OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin, bool aIsApp,
|
||||
uint64_t aLimit, uint64_t aUsage, int64_t aAccessTime)
|
||||
: mGroupInfo(aGroupInfo), mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage),
|
||||
mAccessTime(aAccessTime)
|
||||
mAccessTime(aAccessTime), mIsApp(aIsApp)
|
||||
{
|
||||
MOZ_COUNT_CTOR(OriginInfo);
|
||||
}
|
||||
@ -91,6 +91,12 @@ public:
|
||||
return mAccessTime;
|
||||
}
|
||||
|
||||
bool
|
||||
IsTreatedAsPersistent() const;
|
||||
|
||||
bool
|
||||
IsTreatedAsTemporary() const;
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~OriginInfo()
|
||||
@ -124,10 +130,11 @@ private:
|
||||
nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
|
||||
|
||||
GroupInfo* mGroupInfo;
|
||||
nsCString mOrigin;
|
||||
uint64_t mLimit;
|
||||
const nsCString mOrigin;
|
||||
const uint64_t mLimit;
|
||||
uint64_t mUsage;
|
||||
int64_t mAccessTime;
|
||||
const bool mIsApp;
|
||||
};
|
||||
|
||||
class OriginInfoLRUComparator
|
||||
@ -155,26 +162,16 @@ class GroupInfo MOZ_FINAL
|
||||
friend class QuotaObject;
|
||||
|
||||
public:
|
||||
GroupInfo(PersistenceType aPersistenceType, const nsACString& aGroup)
|
||||
: mPersistenceType(aPersistenceType), mGroup(aGroup), mUsage(0)
|
||||
GroupInfo(GroupInfoPair* aGroupInfoPair, PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup)
|
||||
: mGroupInfoPair(aGroupInfoPair), mPersistenceType(aPersistenceType),
|
||||
mGroup(aGroup), mUsage(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(GroupInfo);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GroupInfo)
|
||||
|
||||
bool
|
||||
IsForPersistentStorage() const
|
||||
{
|
||||
return mPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
|
||||
bool
|
||||
IsForTemporaryStorage() const
|
||||
{
|
||||
return mPersistenceType == PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~GroupInfo()
|
||||
@ -205,8 +202,18 @@ private:
|
||||
return !mOriginInfos.IsEmpty();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
LockedGetTemporaryUsage();
|
||||
|
||||
void
|
||||
LockedGetTemporaryOriginInfos(nsTArray<OriginInfo*>* aOriginInfos);
|
||||
|
||||
void
|
||||
LockedRemoveTemporaryOriginInfos();
|
||||
|
||||
nsTArray<nsRefPtr<OriginInfo> > mOriginInfos;
|
||||
|
||||
GroupInfoPair* mGroupInfoPair;
|
||||
PersistenceType mPersistenceType;
|
||||
nsCString mGroup;
|
||||
uint64_t mUsage;
|
||||
@ -215,6 +222,7 @@ private:
|
||||
class GroupInfoPair
|
||||
{
|
||||
friend class QuotaManager;
|
||||
friend class QuotaObject;
|
||||
|
||||
public:
|
||||
GroupInfoPair()
|
||||
|
@ -1,29 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_storageprivilege_h__
|
||||
#define mozilla_dom_quota_storageprivilege_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
enum StoragePrivilege {
|
||||
// Quota not tracked, persistence type is always "persistent".
|
||||
Chrome,
|
||||
|
||||
// Quota tracked, persistence type can be either "persistent" or "temporary".
|
||||
// The permission "defaul-persistent-storage" is used to determine the
|
||||
// default persistence type.
|
||||
Content,
|
||||
|
||||
// Only needed for IPC serialization helper, should never be used in code.
|
||||
Invalid
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_storageprivilege_h__
|
@ -26,7 +26,6 @@ EXPORTS.mozilla.dom.quota += [
|
||||
'QuotaCommon.h',
|
||||
'QuotaManager.h',
|
||||
'QuotaObject.h',
|
||||
'StoragePrivilege.h',
|
||||
'UsageInfo.h',
|
||||
'Utilities.h',
|
||||
]
|
||||
|
@ -56,12 +56,11 @@ SVGTransformableElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||
nsSVGElement::GetAttributeChangeHint(aAttribute, aModType);
|
||||
if (aAttribute == nsGkAtoms::transform ||
|
||||
aAttribute == nsGkAtoms::mozAnimateMotionDummyAttr) {
|
||||
// We add nsChangeHint_UpdateOverflow so that nsFrame::UpdateOverflow()
|
||||
// will be called on us and our ancestors.
|
||||
nsIFrame* frame =
|
||||
const_cast<SVGTransformableElement*>(this)->GetPrimaryFrame();
|
||||
NS_UpdateHint(retval, nsChangeHint_InvalidateRenderingObservers);
|
||||
if (!frame || (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
|
||||
return retval; // no change
|
||||
return retval;
|
||||
}
|
||||
if (aModType == nsIDOMMutationEvent::ADDITION ||
|
||||
aModType == nsIDOMMutationEvent::REMOVAL ||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/types.h>
|
||||
@ -215,7 +216,7 @@ public:
|
||||
mMode(AUTOMOUNTER_DISABLE)
|
||||
{
|
||||
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
|
||||
Volume::RegisterObserver(&mVolumeEventObserver);
|
||||
Volume::RegisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
|
||||
|
||||
// It's possible that the VolumeManager is already in the READY state,
|
||||
// so we call CheckVolumeSettings here to cover that case. Otherwise,
|
||||
@ -228,15 +229,7 @@ public:
|
||||
|
||||
~AutoMounter()
|
||||
{
|
||||
VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
|
||||
VolumeManager::VolumeArray::index_type volIndex;
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
|
||||
if (vol) {
|
||||
vol->UnregisterObserver(&mVolumeEventObserver);
|
||||
}
|
||||
}
|
||||
Volume::UnregisterObserver(&mVolumeEventObserver);
|
||||
Volume::UnregisterVolumeObserver(&mVolumeEventObserver, "AutoMounter");
|
||||
VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
|
||||
}
|
||||
|
||||
@ -257,7 +250,6 @@ public:
|
||||
for (i = 0; i < numVolumes; i++) {
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(i);
|
||||
if (vol) {
|
||||
vol->RegisterObserver(&mVolumeEventObserver);
|
||||
// We need to pick up the intial value of the
|
||||
// ums.volume.NAME.enabled setting.
|
||||
AutoMounterSetting::CheckVolumeSettings(vol->Name());
|
||||
@ -928,6 +920,39 @@ AutoMounter::UpdateState()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vol->State() == nsIVolume::STATE_CHECKMNT) {
|
||||
// vold reports the volume is "Mounted". Need to check if the volume is
|
||||
// accessible by statfs(). Once it can be accessed, set the volume as
|
||||
// STATE_MOUNTED, otherwise, post a delay task of UpdateState to check it
|
||||
// again.
|
||||
struct statfs fsbuf;
|
||||
int rc = MOZ_TEMP_FAILURE_RETRY(statfs(vol->MountPoint().get(), &fsbuf));
|
||||
if (rc == -1) {
|
||||
// statfs() failed. Stay in STATE_CHECKMNT. Any failures here
|
||||
// are probably non-recoverable, so we need to wait until
|
||||
// something else changes the state back to IDLE/UNMOUNTED, etc.
|
||||
ERR("statfs failed for '%s': errno = %d (%s)", vol->NameStr(), errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
static int delay = 250;
|
||||
if (fsbuf.f_blocks == 0) {
|
||||
if (delay <= 4000) {
|
||||
LOG("UpdateState: Volume '%s' is inaccessible, checking again in %d msec", vol->NameStr(), delay);
|
||||
MessageLoopForIO::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &AutoMounter::UpdateState),
|
||||
delay);
|
||||
delay *= 2;
|
||||
} else {
|
||||
LOG("UpdateState: Volume '%s' is inaccessible, giving up", vol->NameStr());
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
delay = 250;
|
||||
vol->SetState(nsIVolume::STATE_MOUNTED);
|
||||
}
|
||||
}
|
||||
|
||||
if ((tryToShare && vol->IsSharingEnabled()) ||
|
||||
vol->IsFormatRequested() ||
|
||||
vol->IsUnmountRequested()) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user