Merge m-c to fx-team a=merge

This commit is contained in:
Wes Kocher 2014-11-04 20:40:56 -08:00
commit df5afea581
212 changed files with 10935 additions and 5347 deletions

View File

@ -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.

View File

@ -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"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "6bf7a21e0dbf766076bfd1c15e59dea7f25a4c13",
"revision": "1d065718099172104bee68bc190b583a0472a5e3",
"repo_path": "/integration/gaia-central"
}

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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; }])

View File

@ -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

View File

@ -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__':

View File

@ -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

View File

@ -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
#

View File

@ -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'"

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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

View 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>

View File

@ -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,

View File

@ -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.

View File

@ -1546,7 +1546,7 @@ private:
return data->mConstructorCID != nullptr;
}
return nullptr;
return false;
}
static bool IsConstructable(const nsGlobalNameStruct *aNameStruct)
{

View File

@ -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();

View File

@ -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)
{

View File

@ -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")

View File

@ -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;

View File

@ -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

View File

@ -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]

View File

@ -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;
}

View File

@ -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

View File

@ -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");

View File

@ -726,7 +726,7 @@ protected:
mozilla::gfx::Rect* bounds,
mozilla::gfx::Rect dest,
mozilla::gfx::Rect src,
gfxIntSize imgSize);
gfx::IntSize imgSize);
nsString& GetFont()
{

View File

@ -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

View File

@ -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'''

View File

@ -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');

View File

@ -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);
})();

View File

@ -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',
]

View 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

View 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

View File

@ -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;
}

View 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);
}

View 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 */

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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],

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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();
}

View File

@ -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,

View File

@ -93,7 +93,6 @@ FAIL_ON_WARNINGS = True
LOCAL_INCLUDES += [
'/db/sqlite3/src',
'/dom/base',
'/dom/quota',
'/dom/storage',
'/ipc/glue',
'/xpcom/build',

View File

@ -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]

View File

@ -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();

View File

@ -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;
},

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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),

View File

@ -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,

View File

@ -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
}

View File

@ -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();

View File

@ -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

View 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>

View File

@ -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) {

View File

@ -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',

View File

@ -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();

View File

@ -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) {

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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')

View File

@ -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)]

View File

@ -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]);

View File

@ -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);
});

View File

@ -0,0 +1,5 @@
[DEFAULT]
head =
tail =
[test_HCIEventTransactionSystemMessageConfigurator.js]

View File

@ -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,

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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()

View File

@ -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__

View File

@ -26,7 +26,6 @@ EXPORTS.mozilla.dom.quota += [
'QuotaCommon.h',
'QuotaManager.h',
'QuotaObject.h',
'StoragePrivilege.h',
'UsageInfo.h',
'Utilities.h',
]

View File

@ -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 ||

View File

@ -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