Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-09-04 15:22:28 +02:00
commit 641e64fe3f
355 changed files with 3507 additions and 3718 deletions

View File

@ -4,9 +4,7 @@
# 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/.
LIBRARY_NAME = 'IA2Marshal'
FORCE_SHARED_LIB = True
SharedLibrary('IA2Marshal')
DEFINES['REGISTER_PROXY_DLL'] = True

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'AccessibleMarshal'
SharedLibrary('AccessibleMarshal')
GENERATED_SOURCES += [
'dlldata.c',
@ -16,8 +16,6 @@ GENERATED_SOURCES += [
'ISimpleDOMText_p.c',
]
FORCE_SHARED_LIB = True
DEFINES['REGISTER_PROXY_DLL'] = True
DEFFILE = SRCDIR + '/AccessibleMarshal.def'

View File

@ -6,9 +6,9 @@
if not CONFIG['LIBXUL_SDK']:
if CONFIG['GAIADIR']:
PROGRAM = CONFIG['MOZ_APP_NAME'] + "-bin"
Program(CONFIG['MOZ_APP_NAME'] + "-bin")
else:
PROGRAM = CONFIG['MOZ_APP_NAME']
Program(CONFIG['MOZ_APP_NAME'])
if CONFIG['MOZ_B2G_LOADER']:
SOURCES += [
'B2GLoader.cpp',

View File

@ -513,6 +513,10 @@ let settingsToObserve = {
prefName: 'dom.sms.strict7BitEncoding',
defaultValue: false
},
'ril.sms.maxReadAheadEntries': {
prefName: 'dom.sms.maxReadAheadEntries',
defaultValue: 7
},
'ui.touch.radius.leftmm': {
resetToPref: true
},

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="4b4336c73c081b39776d399835ce4853aee5cc1c">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="68af8bfafdf9e35f4db0ae60e087cbf8f6d7ee6d"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="4b4336c73c081b39776d399835ce4853aee5cc1c">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="4b4336c73c081b39776d399835ce4853aee5cc1c">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="68af8bfafdf9e35f4db0ae60e087cbf8f6d7ee6d"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "7448e582578f9d88a6d24a8f372cb7a6343e25e3",
"revision": "9c3a4beb0c7c08c6a20dd406210f3c671557e121",
"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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="68af8bfafdf9e35f4db0ae60e087cbf8f6d7ee6d"/>

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="008026e932b64b4a70b9931c3da96986583bc8d4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de59e0c3614dd0061881fe284e9f2d74fa0d1d5d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -4,7 +4,7 @@
# 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/.
PROGRAM = CONFIG['MOZ_APP_NAME']
Program(CONFIG['MOZ_APP_NAME'])
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [

View File

@ -6,7 +6,7 @@
DIRS += ['profile/extensions']
PROGRAM = CONFIG['MOZ_APP_NAME']
Program(CONFIG['MOZ_APP_NAME'])
SOURCES += [
'nsBrowserApp.cpp',

View File

@ -4,7 +4,7 @@
# 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/.
PROGRAM = 'CommandExecuteHandler'
Program('CommandExecuteHandler')
SOURCES += [
'CEHHelper.cpp',

View File

@ -4,7 +4,7 @@
# 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/.
PROGRAM = 'linktool'
Program('linktool')
SOURCES += [
'linktool.cpp',

View File

@ -4,7 +4,7 @@
# 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/.
PROGRAM = 'metrotestharness'
Program('metrotestharness')
SOURCES += [
'metrotestharness.cpp',

View File

@ -108,7 +108,7 @@ libs:: $(topsrcdir)/tools/rb/fix_macosx_stack.py
endif
ifeq ($(OS_ARCH),Linux)
libs:: $(topsrcdir)/tools/rb/fix-linux-stack.pl
libs:: $(topsrcdir)/tools/rb/fix_linux_stack.py
$(INSTALL) $< $(DIST)/bin
endif

View File

@ -68,7 +68,6 @@ _IS_CYGWIN = False
#endif
#expand _IS_CAMINO = __IS_CAMINO__ != 0
#expand _BIN_SUFFIX = __BIN_SUFFIX__
#expand _PERL = __PERL__
#expand _DEFAULT_APP = "./" + __BROWSER_PATH__
#expand _CERTS_SRC_DIR = __CERTS_SRC_DIR__
@ -143,7 +142,6 @@ class Automation(object):
IS_CYGWIN = _IS_CYGWIN
IS_CAMINO = _IS_CAMINO
BIN_SUFFIX = _BIN_SUFFIX
PERL = _PERL
UNIXISH = not IS_WIN32 and not IS_MAC
@ -671,7 +669,6 @@ class Automation(object):
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
""" Look for timeout or crashes and return the status after the process terminates """
stackFixerProcess = None
stackFixerFunction = None
didTimeout = False
hitMaxTime = False
@ -694,12 +691,12 @@ class Automation(object):
stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line)
del sys.path[0]
elif self.IS_DEBUG_BUILD and self.IS_LINUX:
# Run logsource through fix-linux-stack.pl (uses addr2line)
# Run each line through a function in fix_linux_stack.py (uses addr2line)
# This method is preferred for developer machines, so we don't have to run "make buildsymbols".
stackFixerProcess = self.Process([self.PERL, os.path.join(utilityPath, "fix-linux-stack.pl")],
stdin=logsource,
stdout=subprocess.PIPE)
logsource = stackFixerProcess.stdout
sys.path.insert(0, utilityPath)
import fix_linux_stack as stackFixerModule
stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line)
del sys.path[0]
# With metro browser runs this script launches the metro test harness which launches the browser.
# The metro test harness hands back the real browser process id via log output which we need to
@ -725,7 +722,7 @@ class Automation(object):
self.log.info("INFO | automation.py | metro browser sub process id detected: %s", browserProcessId)
if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):
# Kill the application, but continue reading from stack fixer so as not to deadlock on stackFixerProcess.wait().
# Kill the application.
hitMaxTime = True
self.log.info("TEST-UNEXPECTED-FAIL | %s | application ran for longer than allowed maximum time of %d seconds", self.lastTestSeen, int(maxTime))
self.killAndGetStack(proc.pid, utilityPath, debuggerInfo)
@ -743,11 +740,6 @@ class Automation(object):
self.lastTestSeen = "Main app process exited normally"
if status != 0 and not didTimeout and not hitMaxTime:
self.log.info("TEST-UNEXPECTED-FAIL | %s | Exited with code %d during test run", self.lastTestSeen, status)
if stackFixerProcess is not None:
fixerStatus = stackFixerProcess.wait()
automationutils.printstatus(status, "stackFixerProcess")
if fixerStatus != 0 and not didTimeout and not hitMaxTime:
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | Stack fixer process exited with code %d during test run", fixerStatus)
return status
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):

View File

@ -39,20 +39,20 @@ Static Libraries
================
To build a static library, other than defining the source files (see above), one
just needs to define a library name with the ``LIBRARY_NAME`` variable.
just needs to define a library name with the ``Library`` template.
LIBRARY_NAME = 'foo'
Library('foo')
The library file name will be ``libfoo.a`` on UNIX systems and ``foo.lib`` on
Windows.
If the static library needs to aggregate other static libraries, a list of
``LIBRARY_NAME`` can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it
``Library`` names can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it
requires the appended list to be alphanumerically ordered.
USE_LIBS += ['bar', 'baz']
If there are multiple directories containing the same ``LIBRARY_NAME``, it is
If there are multiple directories containing the same ``Library`` name, it is
possible to disambiguate by prefixing with the path to the wanted one (relative
or absolute):
@ -61,7 +61,7 @@ or absolute):
'../relative/baz',
]
Note that the leaf name in those paths is the ``LIBRARY_NAME``, not an actual
Note that the leaf name in those paths is the ``Library`` name, not an actual
file name.
Note that currently, the build system may not create an actual library for
@ -84,10 +84,10 @@ be linked to that bigger library, with the ``FINAL_LIBRARY`` variable.
FINAL_LIBRARY = 'xul'
The ``FINAL_LIBRARY`` value must match a unique ``LIBRARY_NAME`` somewhere
The ``FINAL_LIBRARY`` value must match a unique ``Library`` name somewhere
in the tree.
As a special rule, those intermediate libraries don't need a ``LIBRARY_NAME``
As a special rule, those intermediate libraries don't need a ``Library`` name
for themselves.
@ -95,15 +95,15 @@ Shared Libraries
================
Sometimes, we want shared libraries, a.k.a. dynamic libraries. Such libraries
are defined with the same variables as static libraries, with the addition of
the ``FORCE_SHARED_LIB`` boolean variable:
are defined similarly to static libraries, using the ``SharedLibrary`` template
instead of ``Library``.
FORCE_SHARED_LIB = True
SharedLibrary('foo')
When this variable is set, no static library is built. See further below to
When this template is used, no static library is built. See further below to
build both types of libraries.
With a ``LIBRARY_NAME`` of ``foo``, the library file name will be
With a ``SharedLibrary`` name of ``foo``, the library file name will be
``libfoo.dylib`` on OSX, ``libfoo.so`` on ELF systems (Linux, etc.), and
``foo.dll`` on Windows. On Windows, there is also an import library named
``foo.lib``, used on the linker command line. ``libfoo.dylib`` and
@ -111,51 +111,61 @@ With a ``LIBRARY_NAME`` of ``foo``, the library file name will be
systems.
On OSX, one may want to create a special kind of dynamic library: frameworks.
This is done with the ``IS_FRAMEWORK`` boolean variable.
This is done with the ``Framework`` template.
IS_FRAMEWORK = True
Framework('foo')
With a ``LIBRARY_NAME`` of ``foo``, the framework file name will be ``foo``.
This variable however affects the behavior on all platforms, so it needs to
With a ``Framework`` name of ``foo``, the framework file name will be ``foo``.
This template however affects the behavior on all platforms, so it needs to
be set only on OSX.
Another special kind of library, XPCOM-specific, are XPCOM components. One can
build such a component with the ``IS_COMPONENT`` boolean variable.
build such a component with the ``XPCOMBinaryComponent`` template.
IS_COMPONENT = True
XPCOMBinaryComponent('foo')
Executables
===========
Executables, a.k.a. programs, are, in the simplest form, defined with the
``PROGRAM`` variable.
``Program`` template.
PROGRAM = 'foobar'
Program('foobar')
On UNIX systems, the executable file name will be ``foobar``, while on Windows,
it will be ``foobar.exe``.
Like static and shared libraries, the build system can be instructed to link
libraries to the executable with ``USE_LIBS``, listing various ``LIBRARY_NAME``.
libraries to the executable with ``USE_LIBS``, listing various ``Library``
names.
In some cases, we want to create an executable per source file in the current
directory, in which case we can use the ``SIMPLE_PROGRAMS`` list:
directory, in which case we can use the ``SimplePrograms`` template
SIMPLE_PROGRAMS = [
SimplePrograms([
'FirstProgram',
'SecondProgram',
]
])
The corresponding ``SOURCES`` must match:
Contrary to ``Program``, which requires corresponding ``SOURCES``, when using
``SimplePrograms``, the corresponding ``SOURCES`` are implied. If the
corresponding ``sources`` have an extension different from ``.cpp``, it is
possible to specify the proper extension:
SOURCES += [
'FirstProgram.cpp',
'SecondProgram.c',
]
SimplePrograms([
'ThirdProgram',
'FourthProgram',
], ext='.c')
Similar to ``SIMPLE_PROGRAMS``, is ``CPP_UNIT_TESTS``, which defines, with the
same rules, C++ unit tests programs.
Please note this construct was added for compatibility with what already lives
in the mozilla tree ; it is recommended not to add new simple programs with
sources with a different extension than ``.cpp``.
Similar to ``SimplePrograms``, is the ``CppUnitTests`` template, which defines,
with the same rules, C++ unit tests programs. Like ``SimplePrograms``, it takes
an ``ext`` argument to specify the extension for the corresponding ``SOURCES``,
if it's different from ``.cpp``.
Linking with system libraries
@ -189,10 +199,10 @@ Libraries from third party build system
=======================================
Some libraries in the tree are not built by the moz.build-governed build
system, and there is no ``LIBRARY_NAME`` corresponding to them.
system, and there is no ``Library`` corresponding to them.
However, ``USE_LIBS`` allows to reference such libraries by giving a full
path (like when disambiguating identical ``LIBRARY_NAME``). The same naming
path (like when disambiguating identical ``Library`` names). The same naming
rules apply as other uses of ``USE_LIBS``, so only the library name without
prefix and suffix shall be given.
@ -217,12 +227,12 @@ When both types of libraries are required, one needs to set both
But because static libraries and Windows import libraries have the same file
names, either the static or the shared library name needs to be different
than ``LIBRARY_NAME``.
than the name given to the ``Library`` template.
The ``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME`` variables can be used
to change either the static or the shared library name.
LIBRARY_NAME = 'foo'
Library('foo')
STATIC_LIBRARY_NAME = 'foo_s'
With the above, on Windows, ``foo_s.lib`` will be the static library,
@ -231,25 +241,25 @@ With the above, on Windows, ``foo_s.lib`` will be the static library,
In some cases, for convenience, it is possible to set both
``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME``. For example:
LIBRARY_NAME = 'mylib'
Library('mylib')
STATIC_LIBRARY_NAME = 'mylib_s'
SHARED_LIBRARY_NAME = CONFIG['SHARED_NAME']
This allows to use ``mylib`` in the ``USE_LIBS`` of another library or
executable.
When refering to a ``LIBRARY_NAME`` building both types of libraries in
When refering to a ``Library`` name building both types of libraries in
``USE_LIBS``, the shared library is chosen to be linked. But sometimes,
it is wanted to link the static version, in which case the ``LIBRARY_NAME``
it is wanted to link the static version, in which case the ``Library`` name
needs to be prefixed with ``static:`` in ``USE_LIBS``
a/moz.build:
LIBRARY_NAME = 'mylib'
Library('mylib')
FORCE_SHARED_LIB = True
FORCE_STATIC_LIB = True
STATIC_LIBRARY_NAME = 'mylib_s'
b/moz.build:
PROGRAM = 'myprog'
Program('myprog')
USE_LIBS += [
'static:mylib',
]
@ -262,18 +272,18 @@ The ``SDK_LIBRARY`` boolean variable defines whether the library in the current
directory is going to be installed in the SDK.
The ``SONAME`` variable declares a "shared object name" for the library. It
defaults to the ``LIBRARY_NAME`` or the ``SHARED_LIBRARY_NAME`` if set. When
defaults to the ``Library`` name or the ``SHARED_LIBRARY_NAME`` if set. When
linking to a library with a ``SONAME``, the resulting library or program will
have a dependency on the library with the name corresponding to the ``SONAME``
instead of ``LIBRARY_NAME``. This only impacts ELF systems.
instead of the ``Library`` name. This only impacts ELF systems.
a/moz.build:
LIBRARY_NAME = 'mylib'
Library('mylib')
b/moz.build:
LIBRARY_NAME = 'otherlib'
Library('otherlib')
SONAME = 'foo'
c/moz.build:
PROGRAM = 'myprog'
Program('myprog')
USE_LIBS += [
'mylib',
'otherlib',

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'stlport_static'
Library('stlport_static')
FORCE_STATIC_LIB = True

View File

@ -4,6 +4,105 @@
# 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/.
@template
def StdCppCompat():
'''Template for libstdc++ compatibility for target binaries.'''
if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
USE_LIBS += ['stdc++compat']
@template
def Program(name):
'''Template for program executables.'''
PROGRAM = name
StdCppCompat()
@template
def SimplePrograms(names, ext='.cpp'):
'''Template for simple program executables.
Those have a single source with the same base name as the executable.
'''
SIMPLE_PROGRAMS += names
SOURCES += ['%s%s' % (name, ext) for name in names]
StdCppCompat()
@template
def CppUnitTests(names, ext='.cpp'):
'''Template for C++ unit tests.
Those have a single source with the same base name as the executable.
'''
CPP_UNIT_TESTS += names
SOURCES += ['%s%s' % (name, ext) for name in names]
StdCppCompat()
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def SharedLibrary(name):
'''Template for shared libraries.'''
Library(name)
FORCE_SHARED_LIB = True
StdCppCompat()
@template
def Framework(name):
'''Template for OSX Frameworks.'''
SharedLibrary(name)
IS_FRAMEWORK = True
@template
def HostStdCppCompat():
'''Template for libstdc++ compatibility for host binaries.'''
if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
HOST_USE_LIBS += ['host_stdc++compat']
@template
def HostProgram(name):
'''Template for build tools executables.'''
HOST_PROGRAM = name
HostStdCppCompat()
@template
def HostSimplePrograms(names, ext='.cpp'):
'''Template for simple build tools executables.
Those have a single source with the same base name as the executable.
'''
HOST_SIMPLE_PROGRAMS += names
HOST_SOURCES += ['%s%s' % (name.replace('host_', ''), ext)
for name in names]
HostStdCppCompat()
@template
def HostLibrary(name):
'''Template for build tools libraries.'''
HOST_LIBRARY_NAME = name
@template
def GeckoBinary():
'''Template for binaries using Gecko.
@ -24,7 +123,7 @@ def XPCOMBinaryComponent(name):
name is the name of the component.
'''
LIBRARY_NAME = name
SharedLibrary(name)
GeckoBinary()

View File

@ -19,7 +19,7 @@ HOST_SOURCES += [
'elfhack.cpp',
]
HOST_PROGRAM = 'elfhack'
HostProgram('elfhack')
DEFINES['ELFHACK_BUILD'] = True

View File

@ -5,11 +5,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
LIBRARY_NAME = 'stdc++compat'
Library('stdc++compat')
SOURCES += ['stdc++compat.cpp']
if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
HOST_LIBRARY_NAME = 'host_stdc++compat'
HostLibrary('host_stdc++compat')
HOST_SOURCES += [
'stdc++compat.cpp',
]

View File

@ -8,9 +8,7 @@ SOURCES += [
'crashinjectdll.cpp',
]
LIBRARY_NAME = 'crashinjectdll'
FORCE_SHARED_LIB = True
SharedLibrary('crashinjectdll')
DEFFILE = SRCDIR + '/crashinjectdll.def'

View File

@ -10,7 +10,7 @@ if CONFIG['_MSC_VER'] and CONFIG['OS_TEST'] != 'x86_64':
TEST_DIRS += ['crashinjectdll']
if CONFIG['ENABLE_TESTS']:
PROGRAM = 'crashinject'
Program('crashinject')
SOURCES += [
'crashinject.cpp',
]

View File

@ -8,9 +8,7 @@ SOURCES += [
'vmwarerecordinghelper.cpp',
]
LIBRARY_NAME = 'vmwarerecordinghelper'
FORCE_SHARED_LIB = True
SharedLibrary('vmwarerecordinghelper')
DEFFILE = '%s/%s.def' % (SRCDIR, LIBRARY_NAME)

View File

@ -19,7 +19,7 @@ interface nsILoadContext;
[ptr] native JSContextPtr(JSContext);
[ptr] native JSObjectPtr(JSObject);
[scriptable, uuid(f6e1e37e-14d0-44fa-a9bb-712bfad6c5f7)]
[scriptable, uuid(3b021962-975e-43b5-8a93-9fc2d20346e9)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@ -199,7 +199,13 @@ interface nsIScriptSecurityManager : nsISupports
* channel owner if there is one, and the codebase principal for the
* channel's URI otherwise. aChannel must not be null.
*/
nsIPrincipal getChannelPrincipal(in nsIChannel aChannel);
nsIPrincipal getChannelResultPrincipal(in nsIChannel aChannel);
/**
* Get the codebase principal for the channel's URI.
* aChannel must not be null.
*/
nsIPrincipal getChannelURIPrincipal(in nsIChannel aChannel);
/**
* Check whether a given principal is a system principal. This allows us

View File

@ -306,8 +306,8 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
}
NS_IMETHODIMP
nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal)
nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal)
{
NS_PRECONDITION(aChannel, "Must have channel!");
nsCOMPtr<nsISupports> owner;
@ -336,14 +336,21 @@ nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
return NS_OK;
}
}
return GetChannelURIPrincipal(aChannel, aPrincipal);
}
// OK, get the principal from the URI. Make sure this does the same thing
NS_IMETHODIMP
nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal)
{
NS_PRECONDITION(aChannel, "Must have channel!");
// Get the principal from the URI. Make sure this does the same thing
// as nsDocument::Reset and XULDocument::StartDocumentLoad.
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(aChannel, loadContext);
@ -1189,7 +1196,7 @@ nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel,
nsIAsyncVerifyRedirectCallback *cb)
{
nsCOMPtr<nsIPrincipal> oldPrincipal;
GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
GetChannelResultPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
nsCOMPtr<nsIURI> newURI;
newChannel->GetURI(getter_AddRefs(newURI));

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'ffi'
Library('ffi')
if CONFIG['MOZ_NATIVE_FFI']:
OS_LIBS += CONFIG['MOZ_FFI_LIBS']

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'freetype'
Library('freetype')
if CONFIG['MOZ_TREE_FREETYPE']:
USE_LIBS += [

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'icu'
Library('icu')
if CONFIG['MOZ_NATIVE_ICU']:
OS_LIBS += CONFIG['MOZ_ICU_LIBS']

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'nspr'
Library('nspr')
if CONFIG['MOZ_FOLD_LIBS']:
# When folding libraries, nspr is actually in the nss library.

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'crmf'
Library('crmf')
if CONFIG['MOZ_NATIVE_NSS']:
OS_LIBS += [l for l in CONFIG['NSS_LIBS'] if l.startswith('-L')]

View File

@ -4,17 +4,16 @@
# 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/.
LIBRARY_NAME = 'nss'
DIRS += ['crmf']
if CONFIG['MOZ_NATIVE_NSS']:
Library('nss')
OS_LIBS += CONFIG['NSS_LIBS']
elif CONFIG['MOZ_FOLD_LIBS']:
SharedLibrary('nss')
# TODO: The library name can be changed when bug 845217 is fixed.
SHARED_LIBRARY_NAME = 'nss3'
FORCE_SHARED_LIB = True
SDK_LIBRARY = True
# Normally, there should be /something/ to ensure nspr is built
@ -38,6 +37,7 @@ elif CONFIG['MOZ_FOLD_LIBS']:
if CONFIG['OS_ARCH'] == 'Linux' and CONFIG['GCC_USE_GNU_LD']:
LD_VERSION_SCRIPT = 'nss3.def'
else:
Library('nss')
USE_LIBS += [
'/security/nss/lib/nss/nss3',
'/security/nss/lib/smime/smime3',

View File

@ -4,19 +4,19 @@
# 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/.
LIBRARY_NAME = 'sqlite'
if CONFIG['MOZ_NATIVE_SQLITE']:
Library('sqlite')
OS_LIBS += CONFIG['SQLITE_LIBS']
else:
DIRS += ['../../../db/sqlite3/src']
if CONFIG['MOZ_FOLD_LIBS']:
Library('sqlite')
# When folding libraries, sqlite is actually in the nss library.
USE_LIBS += [
'nss',
]
else:
FORCE_SHARED_LIB = True
SharedLibrary('sqlite')
SHARED_LIBRARY_NAME = 'mozsqlite3'
if CONFIG['OS_ARCH'] == 'Linux' and CONFIG['GCC_USE_GNU_LD']:

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'zlib'
Library('zlib')
if CONFIG['MOZ_NATIVE_ZLIB']:
OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']

View File

@ -21,7 +21,7 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
'nsinstall.c',
'pathsub.c',
]
HOST_PROGRAM = 'nsinstall_real'
HostProgram('nsinstall_real')
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
DEFINES['GKMEDIAS_SHARED_LIBRARY'] = True

View File

@ -343,8 +343,8 @@ ImportLoader::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
if (nsContentUtils::IsSystemPrincipal(principal)) {
// We should never import non-system documents and run their scripts with system principal!
nsCOMPtr<nsIPrincipal> channelPrincipal;
nsContentUtils::GetSecurityManager()->GetChannelPrincipal(channel,
getter_AddRefs(channelPrincipal));
nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(channel,
getter_AddRefs(channelPrincipal));
if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
return NS_ERROR_FAILURE;
}

View File

@ -5670,7 +5670,7 @@ nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel
nsCOMPtr<nsIPrincipal> oldPrincipal;
nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
GetChannelResultPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
nsCOMPtr<nsIURI> newURI;
aNewChannel->GetURI(getter_AddRefs(newURI));

View File

@ -682,13 +682,15 @@ nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
if (mHasBeenCrossSite) {
// Once we've been cross-site, cross-origin redirects reset our source
// origin.
// origin. Note that we need to call GetChannelURIPrincipal() because
// we are looking for the principal that is actually being loaded and not
// the principal that initiated the load.
nsCOMPtr<nsIPrincipal> oldChannelPrincipal;
nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(aOldChannel, getter_AddRefs(oldChannelPrincipal));
GetChannelURIPrincipal(aOldChannel, getter_AddRefs(oldChannelPrincipal));
nsCOMPtr<nsIPrincipal> newChannelPrincipal;
nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(aNewChannel, getter_AddRefs(newChannelPrincipal));
GetChannelURIPrincipal(aNewChannel, getter_AddRefs(newChannelPrincipal));
if (!oldChannelPrincipal || !newChannelPrincipal) {
rv = NS_ERROR_OUT_OF_MEMORY;
}

View File

@ -2208,15 +2208,15 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
nsCOMPtr<nsIPrincipal> principal;
if (aChannel) {
// Note: this code is duplicated in XULDocument::StartDocumentLoad and
// nsScriptSecurityManager::GetChannelPrincipal.
// nsScriptSecurityManager::GetChannelResultPrincipal.
// Note: this should match nsDocShell::OnLoadingSite
NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
if (securityManager) {
securityManager->GetChannelPrincipal(aChannel,
getter_AddRefs(principal));
securityManager->GetChannelResultPrincipal(aChannel,
getter_AddRefs(principal));
}
}

View File

@ -1461,7 +1461,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// principal as the origin principal
if (aRequest->mCORSMode == CORS_NONE) {
rv = nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal));
GetChannelResultPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -10,14 +10,12 @@ XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
if CONFIG['OS_ARCH'] != 'Darwin':
XPCSHELL_TESTS_MANIFESTS += ['unit_ipc/xpcshell.ini']
CPP_UNIT_TESTS += [
CppUnitTests([
'TestCSPParser',
'TestGetURL',
'TestNativeXMLHttpRequest',
'TestPlainTextSerializer',
]
SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
])
MOCHITEST_MANIFESTS += [
'chrome/mochitest.ini',

View File

@ -94,7 +94,7 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
nsCOMPtr<nsIPrincipal> channelPrincipal;
if (secMan) {
secMan->GetChannelPrincipal(channel, getter_AddRefs(channelPrincipal));
secMan->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal));
}
int16_t decision = nsIContentPolicy::ACCEPT;

View File

@ -534,7 +534,7 @@ ChannelMediaResource::OnDataAvailable(nsIRequest* aRequest,
CopySegmentClosure closure;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (secMan && mChannel) {
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
}
closure.mResource = this;
@ -1406,7 +1406,7 @@ already_AddRefed<nsIPrincipal> FileMediaResource::GetCurrentPrincipal()
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (!secMan || !mChannel)
return nullptr;
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
return principal.forget();
}

View File

@ -740,7 +740,7 @@ already_AddRefed<nsIPrincipal> RtspMediaResource::GetCurrentPrincipal()
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (!secMan || !mChannel)
return nullptr;
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
return principal.forget();
}

View File

@ -4,12 +4,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CPP_UNIT_TESTS += [
CppUnitTests([
'TestAudioBuffers',
'TestAudioMixer'
]
SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
])
FAIL_ON_WARNINGS = True

View File

@ -197,6 +197,7 @@ PlatformCallback(void* decompressionOutputRefCon,
}
if (flags & kVTDecodeInfo_FrameDropped) {
NS_WARNING(" ...frame dropped...");
return;
}
MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(),
"VideoToolbox returned an unexpected image type");

View File

@ -132,6 +132,27 @@ MediaSourceDecoder::CreateSubDecoder(const nsACString& aType)
return mReader->CreateSubDecoder(aType);
}
void
MediaSourceDecoder::AddTrackBuffer(TrackBuffer* aTrackBuffer)
{
MOZ_ASSERT(mReader);
mReader->AddTrackBuffer(aTrackBuffer);
}
void
MediaSourceDecoder::RemoveTrackBuffer(TrackBuffer* aTrackBuffer)
{
MOZ_ASSERT(mReader);
mReader->RemoveTrackBuffer(aTrackBuffer);
}
void
MediaSourceDecoder::OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo)
{
MOZ_ASSERT(mReader);
mReader->OnTrackBufferConfigured(aTrackBuffer, aInfo);
}
void
MediaSourceDecoder::Ended()
{

View File

@ -20,6 +20,7 @@ class MediaResource;
class MediaDecoderStateMachine;
class MediaSourceReader;
class SourceBufferDecoder;
class TrackBuffer;
namespace dom {
@ -46,6 +47,9 @@ public:
void DetachMediaSource();
already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
void AddTrackBuffer(TrackBuffer* aTrackBuffer);
void RemoveTrackBuffer(TrackBuffer* aTrackBuffer);
void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
void Ended();

View File

@ -14,6 +14,7 @@
#include "MediaSourceDecoder.h"
#include "MediaSourceUtils.h"
#include "SourceBufferDecoder.h"
#include "TrackBuffer.h"
#ifdef MOZ_FMP4
#include "MP4Decoder.h"
@ -37,6 +38,8 @@ namespace mozilla {
MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
: MediaDecoderReader(aDecoder)
, mLastAudioTime(-1)
, mLastVideoTime(-1)
, mTimeThreshold(-1)
, mDropAudioBeforeThreshold(false)
, mDropVideoBeforeThreshold(false)
@ -49,25 +52,35 @@ MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
bool
MediaSourceReader::IsWaitingMediaResources()
{
return mDecoders.IsEmpty() && mPendingDecoders.IsEmpty();
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
if (!mTrackBuffers[i]->IsReady()) {
return true;
}
}
return mTrackBuffers.IsEmpty();
}
void
MediaSourceReader::RequestAudioData()
{
MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData", this);
if (!mAudioReader) {
MSE_DEBUG("MediaSourceReader(%p)::RequestAudioData called with no audio reader", this);
MOZ_ASSERT(mPendingDecoders.IsEmpty());
GetCallback()->OnDecodeError();
return;
}
SwitchReaders(SWITCH_OPTIONAL);
if (SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S)) {
MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData switching audio reader", this);
}
mAudioReader->RequestAudioData();
}
void
MediaSourceReader::OnAudioDecoded(AudioData* aSample)
{
MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld mDuration=%lld d=%d",
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
if (mDropAudioBeforeThreshold) {
if (aSample->mTime < mTimeThreshold) {
MSE_DEBUG("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld < mTimeThreshold=%lld",
@ -86,21 +99,22 @@ MediaSourceReader::OnAudioDecoded(AudioData* aSample)
mAudioIsSeeking = false;
aSample->mDiscontinuity = true;
}
mLastAudioTime = aSample->mTime + aSample->mDuration;
GetCallback()->OnAudioDecoded(aSample);
}
void
MediaSourceReader::OnAudioEOS()
{
MSE_DEBUG("MediaSourceReader(%p)::OnAudioEOS reader=%p (readers=%u)",
this, mAudioReader.get(), mDecoders.Length());
if (SwitchReaders(SWITCH_FORCED)) {
MSE_DEBUG("MediaSourceReader(%p)::OnAudioEOS reader=%p (decoders=%u)",
this, mAudioReader.get(), mAudioTrack->Decoders().Length());
if (SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S)) {
// Success! Resume decoding with next audio decoder.
RequestAudioData();
} else if (IsEnded()) {
// End of stream.
MSE_DEBUG("MediaSourceReader(%p)::OnAudioEOS reader=%p EOS (readers=%u)",
this, mAudioReader.get(), mDecoders.Length());
MSE_DEBUG("MediaSourceReader(%p)::OnAudioEOS reader=%p EOS (decoders=%u)",
this, mAudioReader.get(), mAudioTrack->Decoders().Length());
GetCallback()->OnAudioEOS();
}
}
@ -108,26 +122,35 @@ MediaSourceReader::OnAudioEOS()
void
MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold)
{
MSE_DEBUGV("MediaSourceReader(%p)::RequestVideoData(%d, %lld)",
this, aSkipToNextKeyframe, aTimeThreshold);
if (!mVideoReader) {
MSE_DEBUG("MediaSourceReader(%p)::RequestVideoData called with no video reader", this);
MOZ_ASSERT(mPendingDecoders.IsEmpty());
GetCallback()->OnDecodeError();
return;
}
mTimeThreshold = aTimeThreshold;
SwitchReaders(SWITCH_OPTIONAL);
if (aSkipToNextKeyframe) {
mTimeThreshold = aTimeThreshold;
mDropAudioBeforeThreshold = true;
mDropVideoBeforeThreshold = true;
}
if (SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S)) {
MSE_DEBUGV("MediaSourceReader(%p)::RequestVideoData switching video reader", this);
}
mVideoReader->RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
}
void
MediaSourceReader::OnVideoDecoded(VideoData* aSample)
{
MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld mDuration=%lld d=%d",
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
if (mDropVideoBeforeThreshold) {
if (aSample->mTime < mTimeThreshold) {
MSE_DEBUG("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld < mTimeThreshold=%lld",
this, aSample->mTime, mTimeThreshold);
delete aSample;
mVideoReader->RequestVideoData(false, mTimeThreshold);
mVideoReader->RequestVideoData(false, 0);
return;
}
mDropVideoBeforeThreshold = false;
@ -140,7 +163,7 @@ MediaSourceReader::OnVideoDecoded(VideoData* aSample)
mVideoIsSeeking = false;
aSample->mDiscontinuity = true;
}
mLastVideoTime = aSample->mTime + aSample->mDuration;
GetCallback()->OnVideoDecoded(aSample);
}
@ -148,15 +171,15 @@ void
MediaSourceReader::OnVideoEOS()
{
// End of stream. See if we can switch to another video decoder.
MSE_DEBUG("MediaSourceReader(%p)::OnVideoEOS reader=%p (readers=%u)",
this, mVideoReader.get(), mDecoders.Length());
if (SwitchReaders(SWITCH_FORCED)) {
MSE_DEBUG("MediaSourceReader(%p)::OnVideoEOS reader=%p (decoders=%u)",
this, mVideoReader.get(), mVideoTrack->Decoders().Length());
if (SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S)) {
// Success! Resume decoding with next video decoder.
RequestVideoData(false, mTimeThreshold);
RequestVideoData(false, 0);
} else if (IsEnded()) {
// End of stream.
MSE_DEBUG("MediaSourceReader(%p)::OnVideoEOS reader=%p EOS (readers=%u)",
this, mVideoReader.get(), mDecoders.Length());
MSE_DEBUG("MediaSourceReader(%p)::OnVideoEOS reader=%p EOS (decoders=%u)",
this, mVideoReader.get(), mVideoTrack->Decoders().Length());
GetCallback()->OnVideoEOS();
}
}
@ -164,6 +187,7 @@ MediaSourceReader::OnVideoEOS()
void
MediaSourceReader::OnDecodeError()
{
MSE_DEBUG("MediaSourceReader(%p)::OnDecodeError", this);
GetCallback()->OnDecodeError();
}
@ -171,171 +195,105 @@ void
MediaSourceReader::Shutdown()
{
MediaDecoderReader::Shutdown();
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->Shutdown();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->Shutdown();
}
mTrackBuffers.Clear();
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
}
void
MediaSourceReader::BreakCycles()
{
MediaDecoderReader::BreakCycles();
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->BreakCycles();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->BreakCycles();
}
mTrackBuffers.Clear();
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
}
bool
MediaSourceReader::SwitchAudioReader(MediaDecoderReader* aTargetReader)
MediaSourceReader::SwitchAudioReader(double aTarget)
{
if (aTargetReader == mAudioReader) {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding an audio track after ReadMetadata yet.
if (!mAudioTrack) {
return false;
}
if (mAudioReader) {
AudioInfo targetInfo = aTargetReader->GetMediaInfo().mAudio;
auto& decoders = mAudioTrack->Decoders();
for (uint32_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
decoders[i]->GetBuffered(ranges);
MediaDecoderReader* newReader = decoders[i]->GetReader();
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchAudioReader(%f) audioReader=%p reader=%p ranges=%s",
this, aTarget, mAudioReader.get(), newReader, DumpTimeRanges(ranges).get());
AudioInfo targetInfo = newReader->GetMediaInfo().mAudio;
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
// TODO: We can't handle switching audio formats yet.
if (currentInfo.mRate != targetInfo.mRate ||
currentInfo.mChannels != targetInfo.mChannels) {
return false;
continue;
}
mAudioReader->SetIdle();
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
if (newReader->AudioQueue().AtEndOfStream()) {
continue;
}
if (mAudioReader) {
mAudioReader->SetIdle();
}
mAudioReader = newReader;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchAudioReader(%f) switching to audio reader %p",
this, aTarget, mAudioReader.get());
return true;
}
}
mAudioReader = aTargetReader;
mDropAudioBeforeThreshold = true;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchReaders(%p) switching audio reader",
this, mAudioReader.get());
return true;
return false;
}
bool
MediaSourceReader::SwitchVideoReader(MediaDecoderReader* aTargetReader)
MediaSourceReader::SwitchVideoReader(double aTarget)
{
if (aTargetReader == mVideoReader) {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding a video track after ReadMetadata yet.
if (!mVideoTrack) {
return false;
}
if (mVideoReader) {
mVideoReader->SetIdle();
}
mVideoReader = aTargetReader;
mDropVideoBeforeThreshold = true;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchVideoReader(%p) switching video reader",
this, mVideoReader.get());
return true;
}
bool
MediaSourceReader::SwitchReaders(SwitchType aType)
{
InitializePendingDecoders();
// This monitor must be held after the call to InitializePendingDecoders
// as that method also obtains the lock, and then attempts to exit it
// to call ReadMetadata on the readers. If we hold it before the call then
// it remains held during the ReadMetadata call causing a deadlock.
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
bool didSwitch = false;
double decodeTarget = double(mTimeThreshold) / USECS_PER_S;
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
SourceBufferDecoder* decoder = mDecoders[i];
const MediaInfo& info = decoder->GetReader()->GetMediaInfo();
auto& decoders = mVideoTrack->Decoders();
for (uint32_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
decoder->GetBuffered(ranges);
decoders[i]->GetBuffered(ranges);
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchReaders(%d) decoder=%u (%p) discarded=%d"
" reader=%p audioReader=%p videoReader=%p"
" hasAudio=%d hasVideo=%d decodeTarget=%f ranges=%s",
this, aType, i, decoder, decoder->IsDiscarded(),
decoder->GetReader(), mAudioReader.get(), mVideoReader.get(),
info.HasAudio(), info.HasVideo(), decodeTarget,
DumpTimeRanges(ranges).get());
MediaDecoderReader* newReader = decoders[i]->GetReader();
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchVideoReader(%f) videoReader=%p reader=%p ranges=%s",
this, aTarget, mVideoReader.get(), newReader, DumpTimeRanges(ranges).get());
if (decoder->IsDiscarded()) {
continue;
}
if (aType == SWITCH_FORCED || ranges->Find(decodeTarget) != dom::TimeRanges::NoIndex) {
if (info.HasAudio()) {
didSwitch |= SwitchAudioReader(mDecoders[i]->GetReader());
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
if (newReader->VideoQueue().AtEndOfStream()) {
continue;
}
if (info.HasVideo()) {
didSwitch |= SwitchVideoReader(mDecoders[i]->GetReader());
if (mVideoReader) {
mVideoReader->SetIdle();
}
mVideoReader = newReader;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchVideoReader(%f) switching to video reader %p",
this, aTarget, mVideoReader.get());
return true;
}
}
return didSwitch;
}
class ReleaseDecodersTask : public nsRunnable {
public:
explicit ReleaseDecodersTask(nsTArray<nsRefPtr<SourceBufferDecoder>>& aDecoders)
{
mDecoders.SwapElements(aDecoders);
}
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
mDecoders.Clear();
return NS_OK;
}
private:
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
};
void
MediaSourceReader::InitializePendingDecoders()
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mPendingDecoders.Length(); ++i) {
nsRefPtr<SourceBufferDecoder> decoder = mPendingDecoders[i];
MediaDecoderReader* reader = decoder->GetReader();
MSE_DEBUG("MediaSourceReader(%p): Initializing subdecoder %p reader %p",
this, decoder.get(), reader);
MediaInfo mi;
nsAutoPtr<MetadataTags> tags; // TODO: Handle metadata.
nsresult rv;
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
rv = reader->ReadMetadata(&mi, getter_Transfers(tags));
}
reader->SetIdle();
if (NS_FAILED(rv)) {
// XXX: Need to signal error back to owning SourceBuffer.
MSE_DEBUG("MediaSourceReader(%p): Reader %p failed to initialize rv=%x", this, reader, rv);
continue;
}
bool active = false;
if (mi.HasVideo() || mi.HasAudio()) {
MSE_DEBUG("MediaSourceReader(%p): Reader %p has video=%d audio=%d",
this, reader, mi.HasVideo(), mi.HasAudio());
if (mi.HasVideo()) {
MSE_DEBUG("MediaSourceReader(%p): Reader %p video resolution=%dx%d",
this, reader, mi.mVideo.mDisplay.width, mi.mVideo.mDisplay.height);
}
if (mi.HasAudio()) {
MSE_DEBUG("MediaSourceReader(%p): Reader %p audio sampleRate=%d channels=%d",
this, reader, mi.mAudio.mRate, mi.mAudio.mChannels);
}
active = true;
}
if (active) {
mDecoders.AppendElement(decoder);
} else {
MSE_DEBUG("MediaSourceReader(%p): Reader %p not activated", this, reader);
}
}
NS_DispatchToMainThread(new ReleaseDecodersTask(mPendingDecoders));
MOZ_ASSERT(mPendingDecoders.IsEmpty());
mDecoder->NotifyWaitingForResourcesStatusChanged();
return false;
}
MediaDecoderReader*
@ -376,22 +334,51 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType)
reader->SetCallback(callback);
reader->SetTaskQueue(GetTaskQueue());
reader->Init(nullptr);
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MSE_DEBUG("MediaSourceReader(%p)::CreateSubDecoder subdecoder %p subreader %p",
this, decoder.get(), reader.get());
decoder->SetReader(reader);
mPendingDecoders.AppendElement(decoder);
RefPtr<nsIRunnable> task =
NS_NewRunnableMethod(this, &MediaSourceReader::InitializePendingDecoders);
if (NS_FAILED(GetTaskQueue()->Dispatch(task))) {
MSE_DEBUG("MediaSourceReader(%p): Failed to enqueue decoder initialization task", this);
return nullptr;
}
mDecoder->NotifyWaitingForResourcesStatusChanged();
return decoder.forget();
}
namespace {
void
MediaSourceReader::AddTrackBuffer(TrackBuffer* aTrackBuffer)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MSE_DEBUG("MediaSourceReader(%p)::AddTrackBuffer %p", this, aTrackBuffer);
mTrackBuffers.AppendElement(aTrackBuffer);
}
void
MediaSourceReader::RemoveTrackBuffer(TrackBuffer* aTrackBuffer)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MSE_DEBUG("MediaSourceReader(%p)::RemoveTrackBuffer %p", this, aTrackBuffer);
mTrackBuffers.RemoveElement(aTrackBuffer);
if (mAudioTrack == aTrackBuffer) {
mAudioTrack = nullptr;
}
if (mVideoTrack == aTrackBuffer) {
mVideoTrack = nullptr;
}
}
void
MediaSourceReader::OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(mTrackBuffers.Contains(aTrackBuffer));
if (aInfo.HasAudio() && !mAudioTrack) {
MSE_DEBUG("MediaSourceReader(%p)::OnTrackBufferConfigured %p audio", this, aTrackBuffer);
mAudioTrack = aTrackBuffer;
}
if (aInfo.HasVideo() && !mVideoTrack) {
MSE_DEBUG("MediaSourceReader(%p)::OnTrackBufferConfigured %p video", this, aTrackBuffer);
mVideoTrack = aTrackBuffer;
}
mDecoder->NotifyWaitingForResourcesStatusChanged();
}
class ChangeToHaveMetadata : public nsRunnable {
public:
explicit ChangeToHaveMetadata(AbstractMediaDecoder* aDecoder) :
@ -410,23 +397,18 @@ public:
private:
nsRefPtr<AbstractMediaDecoder> mDecoder;
};
}
bool
MediaSourceReader::DecodersContainTime(double aTime)
MediaSourceReader::TrackBuffersContainTime(double aTime)
{
bool found = false;
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
if (!mDecoders[i]->IsDiscarded()) {
if (!mDecoders[i]->ContainsTime(aTime)) {
// No use to continue searching, one source buffer isn't ready yet
return false;
}
found = true;
}
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mAudioTrack && !mAudioTrack->ContainsTime(aTime)) {
return false;
}
return found;
if (mVideoTrack && !mVideoTrack->ContainsTime(aTime)) {
return false;
}
return true;
}
nsresult
@ -435,8 +417,18 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
{
MSE_DEBUG("MediaSourceReader(%p)::Seek(aTime=%lld, aStart=%lld, aEnd=%lld, aCurrent=%lld)",
this, aTime, aStartTime, aEndTime, aCurrentTime);
ResetDecode();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->ResetDecode();
}
// Decoding discontinuity upon seek, reset last times to seek target.
mLastAudioTime = aTime;
mLastVideoTime = aTime;
double target = static_cast<double>(aTime) / USECS_PER_S;
if (!DecodersContainTime(target)) {
if (!TrackBuffersContainTime(target)) {
MSE_DEBUG("MediaSourceReader(%p)::Seek no active buffer contains target=%f", this, target);
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
}
@ -444,28 +436,30 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
// Loop until we have the requested time range in the source buffers.
// This is a workaround for our lack of async functionality in the
// MediaDecoderStateMachine. Bug 979104 implements what we need and
// we'll remove this for an async approach based on that in bug XXXXXXX.
while (!DecodersContainTime(target) && !IsShutdown() && !IsEnded()) {
// we'll remove this for an async approach based on that in bug 1056441.
while (!TrackBuffersContainTime(target) && !IsShutdown() && !IsEnded()) {
MSE_DEBUG("MediaSourceReader(%p)::Seek waiting for target=%f", this, target);
static_cast<MediaSourceDecoder*>(mDecoder)->WaitForData();
SwitchReaders(SWITCH_FORCED);
}
if (IsShutdown()) {
return NS_ERROR_FAILURE;
}
ResetDecode();
if (mAudioReader) {
if (mAudioTrack) {
mAudioIsSeeking = true;
DebugOnly<bool> ok = SwitchAudioReader(target);
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mAudioReader->GetDecoder())->ContainsTime(target));
nsresult rv = mAudioReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p rv=%x", this, mAudioReader.get(), rv);
if (NS_FAILED(rv)) {
return rv;
}
}
if (mVideoReader) {
if (mVideoTrack) {
mVideoIsSeeking = true;
DebugOnly<bool> ok = SwitchVideoReader(target);
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mVideoReader->GetDecoder())->ContainsTime(target));
nsresult rv = mVideoReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p rv=%x", this, mVideoReader.get(), rv);
if (NS_FAILED(rv)) {
@ -478,39 +472,41 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
nsresult
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
{
InitializePendingDecoders();
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata tracks=%u", this, mTrackBuffers.Length());
// ReadMetadata is called *before* checking IsWaitingMediaResources.
if (IsWaitingMediaResources()) {
return NS_OK;
}
if (!mAudioTrack && !mVideoTrack) {
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata missing track: mAudioTrack=%p mVideoTrack=%p",
this, mAudioTrack.get(), mVideoTrack.get());
return NS_ERROR_FAILURE;
}
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata decoders=%u", this, mDecoders.Length());
// XXX: Make subdecoder setup async, so that use cases like bug 989888 can
// work. This will require teaching the state machine about dynamic track
// changes (and multiple tracks).
// Shorter term, make this block until we've got at least one video track
// and lie about having an audio track, then resample/remix as necessary
// to match any audio track added later to fit the format we lied about
// now. For now we just configure what we've got and cross our fingers.
int64_t maxDuration = -1;
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
MediaDecoderReader* reader = mDecoders[i]->GetReader();
MediaInfo mi = reader->GetMediaInfo();
if (mAudioTrack) {
MOZ_ASSERT(mAudioTrack->IsReady());
mAudioReader = mAudioTrack->Decoders()[0]->GetReader();
if (mi.HasVideo() && !mInfo.HasVideo()) {
MOZ_ASSERT(!mVideoReader);
mVideoReader = reader;
mInfo.mVideo = mi.mVideo;
maxDuration = std::max(maxDuration, mDecoders[i]->GetMediaDuration());
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata video reader=%p maxDuration=%lld",
this, reader, maxDuration);
}
if (mi.HasAudio() && !mInfo.HasAudio()) {
MOZ_ASSERT(!mAudioReader);
mAudioReader = reader;
mInfo.mAudio = mi.mAudio;
maxDuration = std::max(maxDuration, mDecoders[i]->GetMediaDuration());
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata audio reader=%p maxDuration=%lld",
this, reader, maxDuration);
}
const MediaInfo& info = mAudioReader->GetMediaInfo();
MOZ_ASSERT(info.HasAudio());
mInfo.mAudio = info.mAudio;
maxDuration = std::max(maxDuration, mAudioReader->GetDecoder()->GetMediaDuration());
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata audio reader=%p maxDuration=%lld",
this, mAudioReader.get(), maxDuration);
}
if (mVideoTrack) {
MOZ_ASSERT(mVideoTrack->IsReady());
mVideoReader = mVideoTrack->Decoders()[0]->GetReader();
const MediaInfo& info = mVideoReader->GetMediaInfo();
MOZ_ASSERT(info.HasVideo());
mInfo.mVideo = info.mVideo;
maxDuration = std::max(maxDuration, mVideoReader->GetDecoder()->GetMediaDuration());
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata video reader=%p maxDuration=%lld",
this, mVideoReader.get(), maxDuration);
}
if (maxDuration != -1) {

View File

@ -19,6 +19,7 @@ namespace mozilla {
class MediaSourceDecoder;
class SourceBufferDecoder;
class TrackBuffer;
namespace dom {
@ -70,22 +71,25 @@ public:
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
int64_t aCurrentTime) MOZ_OVERRIDE;
already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
void AddTrackBuffer(TrackBuffer* aTrackBuffer);
void RemoveTrackBuffer(TrackBuffer* aTrackBuffer);
void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
void Shutdown();
virtual void BreakCycles();
void InitializePendingDecoders();
bool IsShutdown()
{
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
return mDecoder->IsShutdown();
}
// Return true if any of the active decoders contain data for the given time
bool DecodersContainTime(double aTime);
// Return true if all of the active tracks contain data for the specified time.
bool TrackBuffersContainTime(double aTime);
// Mark the reader to indicate that EndOfStream has been called on our MediaSource
void Ended();
@ -94,27 +98,24 @@ public:
bool IsEnded();
private:
enum SwitchType {
SWITCH_OPTIONAL,
SWITCH_FORCED
};
bool SwitchReaders(SwitchType aType);
bool SwitchAudioReader(MediaDecoderReader* aTargetReader);
bool SwitchVideoReader(MediaDecoderReader* aTargetReader);
// These are read and written on the decode task queue threads.
int64_t mTimeThreshold;
bool mDropAudioBeforeThreshold;
bool mDropVideoBeforeThreshold;
nsTArray<nsRefPtr<SourceBufferDecoder>> mPendingDecoders;
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
bool SwitchAudioReader(double aTarget);
bool SwitchVideoReader(double aTarget);
nsRefPtr<MediaDecoderReader> mAudioReader;
nsRefPtr<MediaDecoderReader> mVideoReader;
nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
nsRefPtr<TrackBuffer> mAudioTrack;
nsRefPtr<TrackBuffer> mVideoTrack;
// These are read and written on the decode task queue threads.
int64_t mLastAudioTime;
int64_t mLastVideoTime;
int64_t mTimeThreshold;
bool mDropAudioBeforeThreshold;
bool mDropVideoBeforeThreshold;
bool mEnded;
// For a seek to complete we need to send a sample with

View File

@ -6,14 +6,14 @@
#include "SourceBuffer.h"
#include "AsyncEventRunner.h"
#include "DecoderTraits.h"
#include "MediaDecoder.h"
#include "MediaSourceDecoder.h"
#include "MediaSourceUtils.h"
#include "SourceBufferResource.h"
#include "TrackBuffer.h"
#include "VideoUtils.h"
#include "WebMBufferedParser.h"
#include "mozilla/Endian.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/dom/TimeRanges.h"
#include "mp4_demuxer/BufferStream.h"
@ -23,10 +23,6 @@
#include "nsIRunnable.h"
#include "nsThreadUtils.h"
#include "prlog.h"
#include "SourceBufferDecoder.h"
#include "mozilla/Preferences.h"
#include "WebMBufferedParser.h"
struct JSContext;
class JSObject;
@ -335,19 +331,8 @@ SourceBuffer::GetBuffered(ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
double highestEndTime = 0;
nsRefPtr<TimeRanges> ranges = new TimeRanges();
// TODO: Need to adjust mDecoders so it only tracks active decoders.
// Once we have an abstraction for track buffers, this needs to report the
// intersection of buffered ranges within those track buffers.
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
nsRefPtr<TimeRanges> r = new TimeRanges();
mDecoders[i]->GetBuffered(r);
if (r->Length() > 0) {
highestEndTime = std::max(highestEndTime, r->GetEndTime());
ranges->Union(r);
}
}
double highestEndTime = mTrackBuffer->Buffered(ranges);
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
// Set the end time on the last range to highestEndTime by adding a
// new range spanning the current end time to highestEndTime, which
@ -432,7 +417,7 @@ SourceBuffer::Abort(ErrorResult& aRv)
mAppendWindowEnd = PositiveInfinity<double>();
MSE_DEBUG("SourceBuffer(%p)::Abort() Discarding decoder", this);
DiscardDecoder();
mTrackBuffer->DiscardDecoder();
}
void
@ -464,8 +449,10 @@ SourceBuffer::Detach()
{
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("SourceBuffer(%p)::Detach", this);
Ended();
DiscardDecoder();
if (mTrackBuffer) {
mTrackBuffer->Detach();
}
mTrackBuffer = nullptr;
mMediaSource = nullptr;
}
@ -473,36 +460,34 @@ void
SourceBuffer::Ended()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsAttached());
MSE_DEBUG("SourceBuffer(%p)::Ended", this);
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
mTrackBuffer->DiscardDecoder();
}
SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
: DOMEventTargetHelper(aMediaSource->GetParentObject())
, mMediaSource(aMediaSource)
, mType(aType)
, mLastParsedTimestamp(UnspecifiedNaN<double>())
, mAppendWindowStart(0)
, mAppendWindowEnd(PositiveInfinity<double>())
, mTimestampOffset(0)
, mAppendMode(SourceBufferAppendMode::Segments)
, mUpdating(false)
, mDecoderInitialized(false)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aMediaSource);
mParser = ContainerParser::CreateForMIMEType(aType);
MSE_DEBUG("SourceBuffer(%p)::SourceBuffer: Creating initial decoder, mParser=%p", this, mParser.get());
InitNewDecoder();
mTrackBuffer = new TrackBuffer(aMediaSource->GetDecoder(), aType);
MSE_DEBUG("SourceBuffer(%p)::SourceBuffer: Create mParser=%p mTrackBuffer=%p",
this, mParser.get(), mTrackBuffer.get());
}
SourceBuffer::~SourceBuffer()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mMediaSource);
MSE_DEBUG("SourceBuffer(%p)::~SourceBuffer", this);
DiscardDecoder();
}
MediaSource*
@ -533,37 +518,6 @@ SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
bool
SourceBuffer::InitNewDecoder()
{
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("SourceBuffer(%p)::InitNewDecoder", this);
MOZ_ASSERT(!mDecoder);
MediaSourceDecoder* parentDecoder = mMediaSource->GetDecoder();
nsRefPtr<SourceBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
if (!decoder) {
return false;
}
mDecoder = decoder;
mDecoderInitialized = false;
mDecoders.AppendElement(mDecoder);
return true;
}
void
SourceBuffer::DiscardDecoder()
{
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("SourceBuffer(%p)::DiscardDecoder mDecoder=%p", this, mDecoder.get());
if (mDecoder) {
mDecoder->SetDiscarded();
}
mDecoder = nullptr;
mDecoderInitialized = false;
// XXX: Parser reset may be required?
mLastParsedTimestamp = UnspecifiedNaN<double>();
}
void
SourceBuffer::StartUpdating()
{
@ -610,21 +564,14 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
if (mParser->IsInitSegmentPresent(aData, aLength)) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
if (mDecoderInitialized) {
// Existing decoder has been used, time for a new one.
DiscardDecoder();
}
// If we've got a decoder here, it's not initialized, so we can use it
// rather than creating a new one.
if (!mDecoder && !InitNewDecoder()) {
mTrackBuffer->DiscardDecoder();
if (!mTrackBuffer->NewDecoder()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
MSE_DEBUG("SourceBuffer(%p)::AppendData: Decoder marked as initialized.", this);
mDecoderInitialized = true;
} else if (!mDecoderInitialized) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: Non-init segment appended during initialization.");
} else if (!mTrackBuffer->HasInitSegment()) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: Non-init segment appended during initialization.", this);
Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
ErrorResult dummy;
mMediaSource->EndOfStream(decodeError, dummy);
@ -633,37 +580,39 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
}
double start, end;
if (mParser->ParseStartAndEndTimestamps(aData, aLength, start, end)) {
double lastStart, lastEnd;
mTrackBuffer->LastTimestamp(lastStart, lastEnd);
if (mParser->IsMediaSegmentPresent(aData, aLength) &&
(start < mLastParsedTimestamp || start - mLastParsedTimestamp > 0.1)) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: Data (%f, %f) overlaps %f.",
this, start, end, mLastParsedTimestamp);
(start < lastEnd || start - lastEnd > 0.1)) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: Data last=[%f, %f] overlaps [%f, %f]",
this, lastStart, lastEnd, start, end);
// This data is earlier in the timeline than data we have already
// processed, so we must create a new decoder to handle the decoding.
DiscardDecoder();
mTrackBuffer->DiscardDecoder();
// If we've got a decoder here, it's not initialized, so we can use it
// rather than creating a new one.
if (!InitNewDecoder()) {
if (!mTrackBuffer->NewDecoder()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
MSE_DEBUG("SourceBuffer(%p)::AppendData: Decoder marked as initialized.", this);
mDecoderInitialized = true;
const nsTArray<uint8_t>& initData = mParser->InitData();
mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(initData.Elements()),
initData.Length(),
0);
mDecoder->GetResource()->AppendData(initData.Elements(), initData.Length());
mTrackBuffer->AppendData(initData.Elements(), initData.Length());
mTrackBuffer->SetLastStartTimestamp(start);
}
mLastParsedTimestamp = end;
MSE_DEBUG("SourceBuffer(%p)::AppendData: Segment start=%f end=%f", this, start, end);
mTrackBuffer->SetLastEndTimestamp(end);
MSE_DEBUG("SourceBuffer(%p)::AppendData: Segment last=[%f, %f] [%f, %f]",
this, lastStart, lastEnd, start, end);
}
if (!mTrackBuffer->AppendData(aData, aLength)) {
Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
ErrorResult dummy;
mMediaSource->EndOfStream(decodeError, dummy);
aRv.Throw(NS_ERROR_FAILURE);
return;
}
// XXX: For future reference: NDA call must run on the main thread.
mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
aLength,
mDecoder->GetResource()->GetLength());
mDecoder->GetResource()->AppendData(aData, aLength);
// Eviction uses a byte threshold. If the buffer is greater than the
// number of bytes then data is evicted. The time range for this
@ -673,7 +622,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// TODO: Make the eviction threshold smaller for audio-only streams.
// TODO: Drive evictions off memory pressure notifications.
const uint32_t evict_threshold = 75 * (1 << 20);
bool evicted = mDecoder->GetResource()->EvictData(evict_threshold);
bool evicted = mTrackBuffer->EvictData(evict_threshold);
if (evicted) {
MSE_DEBUG("SourceBuffer(%p)::AppendData Evict; current buffered start=%f",
this, GetBufferedStart());
@ -714,20 +663,13 @@ SourceBuffer::Evict(double aStart, double aEnd)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("SourceBuffer(%p)::Evict(aStart=%f, aEnd=%f)", this, aStart, aEnd);
if (!mDecoder) {
return;
}
double currentTime = mMediaSource->GetDecoder()->GetCurrentTime();
double evictTime = aEnd;
const double safety_threshold = 5;
if (currentTime + safety_threshold >= evictTime) {
evictTime -= safety_threshold;
}
int64_t endOffset = mDecoder->ConvertToByteOffset(evictTime);
if (endOffset > 0) {
mDecoder->GetResource()->EvictBefore(endOffset);
}
MSE_DEBUG("SourceBuffer(%p)::Evict offset=%lld", this, endOffset);
mTrackBuffer->EvictBefore(evictTime);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,

View File

@ -7,14 +7,13 @@
#ifndef mozilla_dom_SourceBuffer_h_
#define mozilla_dom_SourceBuffer_h_
#include "MediaDecoderReader.h"
#include "MediaSource.h"
#include "js/RootingAPI.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/SourceBufferBinding.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/mozalloc.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
@ -31,8 +30,7 @@ namespace mozilla {
class ContainerParser;
class ErrorResult;
class SourceBufferResource;
class SourceBufferDecoder;
class TrackBuffer;
template <typename T> class AsyncEventRunner;
namespace dom {
@ -139,10 +137,7 @@ private:
nsAutoPtr<ContainerParser> mParser;
double mLastParsedTimestamp;
nsRefPtr<SourceBufferDecoder> mDecoder;
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
nsRefPtr<TrackBuffer> mTrackBuffer;
double mAppendWindowStart;
double mAppendWindowEnd;
@ -151,8 +146,6 @@ private:
SourceBufferAppendMode mAppendMode;
bool mUpdating;
bool mDecoderInitialized;
};
} // namespace dom

View File

@ -38,7 +38,6 @@ SourceBufferDecoder::SourceBufferDecoder(MediaResource* aResource,
, mParentDecoder(aParentDecoder)
, mReader(nullptr)
, mMediaDuration(-1)
, mDiscarded(false)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(SourceBufferDecoder);
@ -147,6 +146,10 @@ SourceBufferDecoder::OnStateMachineThread() const
bool
SourceBufferDecoder::OnDecodeThread() const
{
// During initialization we run on our TrackBuffer's task queue.
if (mTaskQueue) {
return mTaskQueue->IsCurrentThreadIn();
}
return mParentDecoder->OnDecodeThread();
}

View File

@ -8,9 +8,10 @@
#define MOZILLA_SOURCEBUFFERDECODER_H_
#include "AbstractMediaDecoder.h"
#include "MediaDecoderReader.h"
#include "SourceBufferResource.h"
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "SourceBufferResource.h"
namespace mozilla {
@ -74,33 +75,30 @@ public:
return mReader;
}
void SetTaskQueue(MediaTaskQueue* aTaskQueue)
{
MOZ_ASSERT((!mTaskQueue && aTaskQueue) || (mTaskQueue && !aTaskQueue));
mTaskQueue = aTaskQueue;
}
// Given a time convert it into an approximate byte offset from the
// cached data. Returns -1 if no such value is computable.
int64_t ConvertToByteOffset(double aTime);
bool IsDiscarded()
{
return mDiscarded;
}
void SetDiscarded()
{
GetResource()->Ended();
mDiscarded = true;
}
// Returns true if the data buffered by this decoder contains the given time.
bool ContainsTime(double aTime);
private:
virtual ~SourceBufferDecoder();
// Our TrackBuffer's task queue, this is only non-null during initialization.
RefPtr<MediaTaskQueue> mTaskQueue;
nsRefPtr<MediaResource> mResource;
AbstractMediaDecoder* mParentDecoder;
nsRefPtr<MediaDecoderReader> mReader;
int64_t mMediaDuration;
bool mDiscarded;
};
} // namespace mozilla

View File

@ -0,0 +1,339 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TrackBuffer.h"
#include "MediaSourceDecoder.h"
#include "SharedThreadPool.h"
#include "MediaTaskQueue.h"
#include "SourceBufferDecoder.h"
#include "SourceBufferResource.h"
#include "VideoUtils.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/dom/TimeRanges.h"
#include "nsError.h"
#include "nsIRunnable.h"
#include "nsThreadUtils.h"
#include "prlog.h"
struct JSContext;
class JSObject;
#ifdef PR_LOGGING
extern PRLogModuleInfo* GetMediaSourceLog();
extern PRLogModuleInfo* GetMediaSourceAPILog();
#define MSE_DEBUG(...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#define MSE_DEBUGV(...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG+1, (__VA_ARGS__))
#define MSE_API(...) PR_LOG(GetMediaSourceAPILog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define MSE_DEBUG(...)
#define MSE_DEBUGV(...)
#define MSE_API(...)
#endif
namespace mozilla {
TrackBuffer::TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& aType)
: mParentDecoder(aParentDecoder)
, mType(aType)
, mLastStartTimestamp(0)
, mLastEndTimestamp(UnspecifiedNaN<double>())
, mHasInit(false)
, mHasAudio(false)
, mHasVideo(false)
{
MOZ_COUNT_CTOR(TrackBuffer);
mTaskQueue = new MediaTaskQueue(GetMediaDecodeThreadPool());
aParentDecoder->AddTrackBuffer(this);
}
TrackBuffer::~TrackBuffer()
{
MOZ_COUNT_DTOR(TrackBuffer);
}
class ReleaseDecoderTask : public nsRunnable {
public:
explicit ReleaseDecoderTask(nsRefPtr<SourceBufferDecoder> aDecoder)
{
mDecoders.AppendElement(aDecoder);
}
explicit ReleaseDecoderTask(nsTArray<nsRefPtr<SourceBufferDecoder>>& aDecoders)
{
mDecoders.SwapElements(aDecoders);
}
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
mDecoders.Clear();
return NS_OK;
}
private:
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
};
void
TrackBuffer::Shutdown()
{
// Shutdown waits for any pending events, which may require the monitor,
// so we must not hold the monitor during this call.
mParentDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
mTaskQueue->Shutdown();
mTaskQueue = nullptr;
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
DiscardDecoder();
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->Shutdown();
}
NS_DispatchToMainThread(new ReleaseDecoderTask(mDecoders));
MOZ_ASSERT(mDecoders.IsEmpty());
mParentDecoder = nullptr;
}
bool
TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mCurrentDecoder) {
return false;
}
SourceBufferResource* resource = mCurrentDecoder->GetResource();
// XXX: For future reference: NDA call must run on the main thread.
mCurrentDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
aLength, resource->GetLength());
resource->AppendData(aData, aLength);
return true;
}
bool
TrackBuffer::EvictData(uint32_t aThreshold)
{
MOZ_ASSERT(NS_IsMainThread());
// XXX Call EvictData on mDecoders?
return mCurrentDecoder->GetResource()->EvictData(aThreshold);
}
void
TrackBuffer::EvictBefore(double aTime)
{
MOZ_ASSERT(NS_IsMainThread());
// XXX Call EvictBefore on mDecoders?
int64_t endOffset = mCurrentDecoder->ConvertToByteOffset(aTime);
if (endOffset > 0) {
mCurrentDecoder->GetResource()->EvictBefore(endOffset);
}
MSE_DEBUG("TrackBuffer(%p)::EvictBefore offset=%lld", this, endOffset);
}
double
TrackBuffer::Buffered(dom::TimeRanges* aRanges)
{
MOZ_ASSERT(NS_IsMainThread());
// XXX check default if mDecoders empty?
double highestEndTime = 0;
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
mDecoders[i]->GetBuffered(r);
if (r->Length() > 0) {
highestEndTime = std::max(highestEndTime, r->GetEndTime());
aRanges->Union(r);
}
}
return highestEndTime;
}
bool
TrackBuffer::NewDecoder()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mCurrentDecoder && mParentDecoder);
nsRefPtr<SourceBufferDecoder> decoder = mParentDecoder->CreateSubDecoder(mType);
if (!decoder) {
return false;
}
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
mCurrentDecoder = decoder;
mLastStartTimestamp = 0;
mLastEndTimestamp = UnspecifiedNaN<double>();
mHasInit = true;
return QueueInitializeDecoder(decoder);
}
bool
TrackBuffer::QueueInitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
{
RefPtr<nsIRunnable> task =
NS_NewRunnableMethodWithArg<nsRefPtr<SourceBufferDecoder>>(this,
&TrackBuffer::InitializeDecoder,
aDecoder);
aDecoder->SetTaskQueue(mTaskQueue);
if (NS_FAILED(mTaskQueue->Dispatch(task))) {
MSE_DEBUG("MediaSourceReader(%p): Failed to enqueue decoder initialization task", this);
return false;
}
return true;
}
void
TrackBuffer::InitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
{
// ReadMetadata may block the thread waiting on data, so it must not be
// called with the monitor held.
mParentDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
MediaDecoderReader* reader = aDecoder->GetReader();
MSE_DEBUG("TrackBuffer(%p): Initializing subdecoder %p reader %p",
this, aDecoder.get(), reader);
MediaInfo mi;
nsAutoPtr<MetadataTags> tags; // TODO: Handle metadata.
nsresult rv = reader->ReadMetadata(&mi, getter_Transfers(tags));
reader->SetIdle();
if (NS_FAILED(rv) || (!mi.HasVideo() && !mi.HasAudio())) {
// XXX: Need to signal error back to owning SourceBuffer.
MSE_DEBUG("TrackBuffer(%p): Reader %p failed to initialize rv=%x audio=%d video=%d",
this, reader, rv, mi.HasAudio(), mi.HasVideo());
aDecoder->SetTaskQueue(nullptr);
NS_DispatchToMainThread(new ReleaseDecoderTask(aDecoder));
return;
}
if (mi.HasVideo()) {
MSE_DEBUG("TrackBuffer(%p): Reader %p video resolution=%dx%d",
this, reader, mi.mVideo.mDisplay.width, mi.mVideo.mDisplay.height);
}
if (mi.HasAudio()) {
MSE_DEBUG("TrackBuffer(%p): Reader %p audio sampleRate=%d channels=%d",
this, reader, mi.mAudio.mRate, mi.mAudio.mChannels);
}
MSE_DEBUG("TrackBuffer(%p): Reader %p activated", this, reader);
RegisterDecoder(aDecoder);
}
void
TrackBuffer::RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
aDecoder->SetTaskQueue(nullptr);
const MediaInfo& info = aDecoder->GetReader()->GetMediaInfo();
// Initialize the track info since this is the first decoder.
if (mDecoders.IsEmpty()) {
mHasAudio = info.HasAudio();
mHasVideo = info.HasVideo();
mParentDecoder->OnTrackBufferConfigured(this, info);
} else if ((info.HasAudio() && !mHasAudio) || (info.HasVideo() && !mHasVideo)) {
MSE_DEBUG("TrackBuffer(%p)::RegisterDecoder with mismatched audio/video tracks", this);
}
mDecoders.AppendElement(aDecoder);
}
void
TrackBuffer::DiscardDecoder()
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
if (mCurrentDecoder) {
mCurrentDecoder->GetResource()->Ended();
}
mCurrentDecoder = nullptr;
}
void
TrackBuffer::Detach()
{
MOZ_ASSERT(NS_IsMainThread());
if (mCurrentDecoder) {
DiscardDecoder();
}
}
bool
TrackBuffer::HasInitSegment()
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
return mHasInit;
}
bool
TrackBuffer::IsReady()
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
MOZ_ASSERT((mHasAudio || mHasVideo) || mDecoders.IsEmpty());
return HasInitSegment() && (mHasAudio || mHasVideo);
}
void
TrackBuffer::LastTimestamp(double& aStart, double& aEnd)
{
MOZ_ASSERT(NS_IsMainThread());
aStart = mLastStartTimestamp;
aEnd = mLastEndTimestamp;
}
void
TrackBuffer::SetLastStartTimestamp(double aStart)
{
MOZ_ASSERT(NS_IsMainThread());
mLastStartTimestamp = aStart;
}
void
TrackBuffer::SetLastEndTimestamp(double aEnd)
{
MOZ_ASSERT(NS_IsMainThread());
mLastEndTimestamp = aEnd;
}
bool
TrackBuffer::ContainsTime(double aTime)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
mDecoders[i]->GetBuffered(r);
if (r->Find(aTime) != dom::TimeRanges::NoIndex) {
return true;
}
}
return false;
}
void
TrackBuffer::BreakCycles()
{
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->BreakCycles();
}
mDecoders.Clear();
mParentDecoder = nullptr;
}
void
TrackBuffer::ResetDecode()
{
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->ResetDecode();
}
}
const nsTArray<nsRefPtr<SourceBufferDecoder>>&
TrackBuffer::Decoders()
{
// XXX assert OnDecodeThread
return mDecoders;
}
} // namespace mozilla

View File

@ -0,0 +1,131 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_TRACKBUFFER_H_
#define MOZILLA_TRACKBUFFER_H_
#include "SourceBufferDecoder.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/mozalloc.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nscore.h"
namespace mozilla {
class MediaSourceDecoder;
namespace dom {
class TimeRanges;
} // namespace dom
class TrackBuffer MOZ_FINAL {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffer);
TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& aType);
void Shutdown();
// Append data to the current decoder. Also responsible for calling
// NotifyDataArrived on the decoder to keep buffered range computation up
// to date. Returns false if the append failed.
bool AppendData(const uint8_t* aData, uint32_t aLength);
bool EvictData(uint32_t aThreshold);
void EvictBefore(double aTime);
// Returns the highest end time of all of the buffered ranges in the
// decoders managed by this TrackBuffer, and returns the union of the
// decoders buffered ranges in aRanges.
double Buffered(dom::TimeRanges* aRanges);
// Create a new decoder, set mCurrentDecoder to the new decoder, and queue
// the decoder for initialization. The decoder is not considered
// initialized until it is added to mDecoders.
bool NewDecoder();
// Mark the current decoder's resource as ended, clear mCurrentDecoder and
// reset mLast{Start,End}Timestamp.
void DiscardDecoder();
void Detach();
// Returns true if an init segment has been appended.
bool HasInitSegment();
// Returns true iff HasInitSegment() and the decoder using that init
// segment has successfully initialized by setting mHas{Audio,Video}..
bool IsReady();
// Query and update mLast{Start,End}Timestamp.
void LastTimestamp(double& aStart, double& aEnd);
void SetLastStartTimestamp(double aStart);
void SetLastEndTimestamp(double aEnd);
// Returns true if any of the decoders managed by this track buffer
// contain aTime in their buffered ranges.
bool ContainsTime(double aTime);
void BreakCycles();
// Call ResetDecode() on each decoder in mDecoders.
void ResetDecode();
// Returns a reference to mDecoders, used by MediaSourceReader to select
// decoders.
// TODO: Refactor to a clenaer interface between TrackBuffer and MediaSourceReader.
const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
private:
~TrackBuffer();
// Queue execution of InitializeDecoder on mTaskQueue.
bool QueueInitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
// Runs decoder initialization including calling ReadMetadata. Runs as an
// event on the decode thread pool.
void InitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
// Adds a successfully initialized decoder to mDecoders and (if it's the
// first decoder initialized), initializes mHasAudio/mHasVideo. Called
// from the decode thread pool.
void RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
// A task queue using the shared media thread pool. Used exclusively to
// initialize (i.e. call ReadMetadata on) decoders as they are created via
// NewDecoder.
RefPtr<MediaTaskQueue> mTaskQueue;
// All of the initialized decoders managed by this TrackBuffer. Access
// protected by mParentDecoder's monitor.
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
// The decoder that the owning SourceBuffer is currently appending data to.
nsRefPtr<SourceBufferDecoder> mCurrentDecoder;
nsRefPtr<MediaSourceDecoder> mParentDecoder;
const nsCString mType;
// The last start and end timestamps added to the TrackBuffer via
// AppendData. Accessed on the main thread only.
double mLastStartTimestamp;
double mLastEndTimestamp;
// Set when the initialization segment is first seen and cached (implied
// by new decoder creation). Protected by mParentDecoder's monitor.
bool mHasInit;
// Set when the first decoder used by this TrackBuffer is initialized.
// Protected by mParentDecoder's monitor.
bool mHasAudio;
bool mHasVideo;
};
} // namespace mozilla
#endif /* MOZILLA_TRACKBUFFER_H_ */

View File

@ -25,6 +25,7 @@ UNIFIED_SOURCES += [
'SourceBufferDecoder.cpp',
'SourceBufferList.cpp',
'SourceBufferResource.cpp',
'TrackBuffer.cpp',
]
FAIL_ON_WARNINGS = True

View File

@ -4,3 +4,9 @@ support-files = seek.webm seek.webm^headers^
[test_MediaSource.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
[test_SplitAppend.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
[test_SplitAppendDelay.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)

View File

@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test whether we can create an MediaSource interface</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result, 0, 318));
sb.appendBuffer(new Uint8Array(e.target.result, 318));
ms.endOfStream();
v.play();
});
r.readAsArrayBuffer(blob);
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,85 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test whether we can create an MediaSource interface</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result, 0, 318));
window.setTimeout(function () {
sb.appendBuffer(new Uint8Array(e.target.result, 318));
ms.endOfStream();
}, 1000);
v.play();
});
r.readAsArrayBuffer(blob);
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>
</html>

View File

@ -4,11 +4,9 @@
# 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/.
CPP_UNIT_TESTS += [
CppUnitTests([
'TestAudioEventTimeline',
]
SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
])
FAIL_ON_WARNINGS = True

View File

@ -2004,7 +2004,7 @@ XULDocument::PrepareToLoad(nsISupports* aContainer,
// Get the document's principal
nsCOMPtr<nsIPrincipal> principal;
nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(aChannel, getter_AddRefs(principal));
GetChannelResultPrincipal(aChannel, getter_AddRefs(principal));
return PrepareToLoadPrototype(mDocumentURI, aCommand, principal, aResult);
}
@ -4516,7 +4516,7 @@ XULDocument::ParserObserver::OnStartRequest(nsIRequest *request,
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (channel && secMan) {
nsCOMPtr<nsIPrincipal> principal;
secMan->GetChannelPrincipal(channel, getter_AddRefs(principal));
secMan->GetChannelResultPrincipal(channel, getter_AddRefs(principal));
// Failure there is ok -- it'll just set a (safe) null principal
mPrototype->SetDocumentPrincipal(principal);

View File

@ -6580,7 +6580,7 @@ NS_IMETHODIMP nsDocShell::SetupRefreshURI(nsIChannel * aChannel)
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal;
rv = secMan->GetChannelPrincipal(aChannel, getter_AddRefs(principal));
rv = secMan->GetChannelResultPrincipal(aChannel, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
SetupReferrerFromChannel(aChannel);

View File

@ -4,11 +4,9 @@
# 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/.
CPP_UNIT_TESTS += [
CppUnitTests([
'TestAudioChannelService',
]
SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
])
if CONFIG['OS_ARCH'] == 'WINNT':
DEFINES['NOMINMAX'] = True

View File

@ -12,7 +12,7 @@ DEFINES.update({
# Do NOT export this library. We don't actually want our test code
# being added to libxul or anything.
LIBRARY_NAME = 'dombindings_test_s'
Library('dombindings_test_s')
EXTRA_COMPONENTS += [
'TestInterfaceJS.js',

View File

@ -4,11 +4,9 @@
# 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/.
CPP_UNIT_TESTS += [
CppUnitTests([
'TestWebGLElementArrayCache',
]
SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
])
FAIL_ON_WARNINGS = True

49
dom/icc/Assertions.cpp Normal file
View File

@ -0,0 +1,49 @@
/* 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 "mozilla/dom/MozIccBinding.h"
#include "nsIIccProvider.h"
namespace mozilla {
namespace dom {
#define ASSERT_ICC_CARD_STATE_EQUALITY(webidlState, xpidlState) \
static_assert(static_cast<uint32_t>(IccCardState::webidlState) == nsIIccProvider::xpidlState, \
"IccCardState::" #webidlState " should equal to nsIIccProvider::" #xpidlState)
ASSERT_ICC_CARD_STATE_EQUALITY(Unknown, CARD_STATE_UNKNOWN);
ASSERT_ICC_CARD_STATE_EQUALITY(Ready, CARD_STATE_READY);
ASSERT_ICC_CARD_STATE_EQUALITY(PinRequired, CARD_STATE_PIN_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(PukRequired, CARD_STATE_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(PermanentBlocked, CARD_STATE_PERMANENT_BLOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(PersonalizationInProgress, CARD_STATE_PERSONALIZATION_IN_PROGRESS);
ASSERT_ICC_CARD_STATE_EQUALITY(PersonalizationReady, CARD_STATE_PERSONALIZATION_READY);
ASSERT_ICC_CARD_STATE_EQUALITY(NetworkLocked, CARD_STATE_NETWORK_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(NetworkSubsetLocked, CARD_STATE_NETWORK_SUBSET_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(CorporateLocked, CARD_STATE_CORPORATE_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(ServiceProviderLocked, CARD_STATE_SERVICE_PROVIDER_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(SimPersonalizationLocked, CARD_STATE_SIM_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(NetworkPukRequired, CARD_STATE_NETWORK_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(NetworkSubsetPukRequired, CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(CorporatePukRequired, CARD_STATE_CORPORATE_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(ServiceProviderPukRequired, CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(SimPersonalizationPukRequired, CARD_STATE_SIM_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(Network1Locked, CARD_STATE_NETWORK1_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(Network2Locked, CARD_STATE_NETWORK2_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(HrpdNetworkLocked, CARD_STATE_HRPD_NETWORK_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimCorporateLocked, CARD_STATE_RUIM_CORPORATE_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimServiceProviderLocked, CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimPersonalizationLocked, CARD_STATE_RUIM_LOCKED);
ASSERT_ICC_CARD_STATE_EQUALITY(Network1PukRequired, CARD_STATE_NETWORK1_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(Network2PukRequired, CARD_STATE_NETWORK2_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(HrpdNetworkPukRequired, CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimCorporatePukRequired, CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimServiceProviderPukRequired, CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(RuimPersonalizationPukRequired, CARD_STATE_RUIM_PUK_REQUIRED);
ASSERT_ICC_CARD_STATE_EQUALITY(Illegal, CARD_STATE_ILLEGAL);
#undef ASSERT_ICC_CARD_STATE_EQUALITY
} // namespace dom
} // namespace mozilla

View File

@ -100,19 +100,20 @@ Icc::GetIccInfo() const
return iccInfo.forget();
}
void
Icc::GetCardState(nsString& aCardState) const
Nullable<IccCardState>
Icc::GetCardState() const
{
aCardState.SetIsVoid(true);
Nullable<IccCardState> result;
if (!mProvider) {
return;
uint32_t cardState = nsIIccProvider::CARD_STATE_UNDETECTED;
if (mProvider &&
NS_SUCCEEDED(mProvider->GetCardState(mClientId, &cardState)) &&
cardState != nsIIccProvider::CARD_STATE_UNDETECTED) {
MOZ_ASSERT(cardState < static_cast<uint32_t>(IccCardState::EndGuard_));
result.SetValue(static_cast<IccCardState>(cardState));
}
nsresult rv = mProvider->GetCardState(mClientId, aCardState);
if (NS_FAILED(rv)) {
aCardState.SetIsVoid(true);
}
return result;
}
void

View File

@ -5,6 +5,7 @@
#ifndef mozilla_dom_Icc_h
#define mozilla_dom_Icc_h
#include "mozilla/dom/MozIccBinding.h" // For IccCardState
#include "mozilla/DOMEventTargetHelper.h"
#include "nsIIccProvider.h"
@ -49,8 +50,8 @@ public:
already_AddRefed<nsIDOMMozIccInfo>
GetIccInfo() const;
void
GetCardState(nsString& aCardState) const;
Nullable<IccCardState>
GetCardState() const;
void
SendStkResponse(const JSContext* aCx, JS::Handle<JS::Value> aCommand,

View File

@ -20,9 +20,43 @@ interface nsIIccListener : nsISupports
/**
* XPCOM component (in the content process) that provides the ICC information.
*/
[scriptable, uuid(7c67ab92-52a3-4e11-995c-c0ad2f66c4cb)]
[scriptable, uuid(aa404b6e-fcfa-4bd2-bc46-e4e94b603ca7)]
interface nsIIccProvider : nsISupports
{
// MUST match enum IccCardState in MozIcc.webidl!
const unsigned long CARD_STATE_UNKNOWN = 0;
const unsigned long CARD_STATE_READY = 1;
const unsigned long CARD_STATE_PIN_REQUIRED = 2;
const unsigned long CARD_STATE_PUK_REQUIRED = 3;
const unsigned long CARD_STATE_PERMANENT_BLOCKED = 4;
const unsigned long CARD_STATE_PERSONALIZATION_IN_PROGRESS = 5;
const unsigned long CARD_STATE_PERSONALIZATION_READY = 6;
const unsigned long CARD_STATE_NETWORK_LOCKED = 7;
const unsigned long CARD_STATE_NETWORK_SUBSET_LOCKED = 8;
const unsigned long CARD_STATE_CORPORATE_LOCKED = 9;
const unsigned long CARD_STATE_SERVICE_PROVIDER_LOCKED = 10;
const unsigned long CARD_STATE_SIM_LOCKED = 11;
const unsigned long CARD_STATE_NETWORK_PUK_REQUIRED = 12;
const unsigned long CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
const unsigned long CARD_STATE_CORPORATE_PUK_REQUIRED = 14;
const unsigned long CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
const unsigned long CARD_STATE_SIM_PUK_REQUIRED = 16;
const unsigned long CARD_STATE_NETWORK1_LOCKED = 17;
const unsigned long CARD_STATE_NETWORK2_LOCKED = 18;
const unsigned long CARD_STATE_HRPD_NETWORK_LOCKED = 19;
const unsigned long CARD_STATE_RUIM_CORPORATE_LOCKED = 20;
const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
const unsigned long CARD_STATE_RUIM_LOCKED = 22;
const unsigned long CARD_STATE_NETWORK1_PUK_REQUIRED = 23;
const unsigned long CARD_STATE_NETWORK2_PUK_REQUIRED = 24;
const unsigned long CARD_STATE_HRPD_NETWORK_PUK_REQUIRED = 25;
const unsigned long CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
const unsigned long CARD_STATE_RUIM_PUK_REQUIRED = 28;
const unsigned long CARD_STATE_ILLEGAL = 29;
const unsigned long CARD_STATE_UNDETECTED = 4294967295; // UINT32_MAX
/**
* Called when a content process registers receiving unsolicited messages from
* RadioInterfaceLayer in the chrome process. Only a content process that has
@ -39,7 +73,7 @@ interface nsIIccProvider : nsISupports
/**
* Card State
*/
DOMString getCardState(in unsigned long clientId);
unsigned long getCardState(in unsigned long clientId);
/**
* STK interfaces.

View File

@ -11,6 +11,10 @@ EXPORTS.mozilla.dom += [
'IccManager.h',
]
UNIFIED_SOURCES += [
'Assertions.cpp',
]
SOURCES += [
'Icc.cpp',
'IccListener.cpp',

View File

@ -2,8 +2,6 @@
* 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 "base/linked_ptr.h"
#include "mozilla/ModuleUtils.h"
#include "nsIClassInfoImpl.h"

View File

@ -9,10 +9,9 @@ SOURCES += [
'gmp-fake.cpp'
]
LIBRARY_NAME = "fake"
SharedLibrary("fake")
USE_STATIC_LIBS = True
FORCE_SHARED_LIB = True
NO_VISIBILITY_FLAGS = True
# Don't use STL wrappers; this isn't Gecko code
DISABLE_STL_WRAPPING = True

View File

@ -8,11 +8,94 @@
#include "nsIDOMDOMRequest.h"
#include "nsIDOMMozSmsMessage.h"
#include "nsIMobileMessageCallback.h"
#include "DOMCursor.h"
#include "nsServiceManagerUtils.h" // for do_GetService
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(MobileMessageCursor, DOMCursor,
mPendingResults)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MobileMessageCursor)
NS_INTERFACE_MAP_END_INHERITING(DOMCursor)
NS_IMPL_ADDREF_INHERITED(MobileMessageCursor, DOMCursor)
NS_IMPL_RELEASE_INHERITED(MobileMessageCursor, DOMCursor)
MobileMessageCursor::MobileMessageCursor(nsPIDOMWindow* aWindow,
nsICursorContinueCallback* aCallback)
: DOMCursor(aWindow, aCallback)
{
}
NS_IMETHODIMP
MobileMessageCursor::Continue()
{
// We have originally:
//
// DOMCursor::Continue()
// +-> DOMCursor::Continue(ErrorResult& aRv)
//
// Now it becomes:
//
// MobileMessageCursor::Continue()
// +-> DOMCursor::Continue()
// +-> MobileMessageCursor::Continue(ErrorResult& aRv)
// o-> DOMCursor::Continue(ErrorResult& aRv)
return DOMCursor::Continue();
}
void
MobileMessageCursor::Continue(ErrorResult& aRv)
{
// An ordinary DOMCursor works in following flow:
//
// DOMCursor::Continue()
// +-> DOMCursor::Reset()
// +-> nsICursorContinueCallback::HandleContinue()
// +-> nsIMobileMessageCursorCallback::NotifyCursorResult()
// +-> DOMCursor::FireSuccess()
//
// With no pending result, we call to |DOMCursor::Continue()| as usual.
if (!mPendingResults.Length()) {
DOMCursor::Continue(aRv);
return;
}
// Otherwise, reset current result and fire a success event with the last
// pending one.
Reset();
nsresult rv = FireSuccessWithNextPendingResult();
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
nsresult
MobileMessageCursor::FireSuccessWithNextPendingResult()
{
// We're going to pop the last element from mPendingResults, so it must not
// be empty.
MOZ_ASSERT(mPendingResults.Length());
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(GetOwner()))) {
return NS_ERROR_FAILURE;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> val(cx);
nsresult rv =
nsContentUtils::WrapNative(cx, mPendingResults.LastElement(), &val);
NS_ENSURE_SUCCESS(rv, rv);
mPendingResults.RemoveElementAt(mPendingResults.Length() - 1);
FireSuccess(val);
return NS_OK;
}
namespace mobilemessage {
NS_IMPL_CYCLE_COLLECTION(MobileMessageCursorCallback, mDOMCursor)
@ -55,21 +138,29 @@ MobileMessageCursorCallback::NotifyCursorError(int32_t aError)
}
NS_IMETHODIMP
MobileMessageCursorCallback::NotifyCursorResult(nsISupports* aResult)
MobileMessageCursorCallback::NotifyCursorResult(nsISupports** aResults,
uint32_t aSize)
{
MOZ_ASSERT(mDOMCursor);
// We should only be notified with valid results. Or, either
// |NotifyCursorDone()| or |NotifyCursorError()| should be called instead.
MOZ_ASSERT(aResults && *aResults && aSize);
// There shouldn't be unexpected notifications before |Continue()| is called.
nsTArray<nsCOMPtr<nsISupports>>& pending = mDOMCursor->mPendingResults;
MOZ_ASSERT(pending.Length() == 0);
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mDOMCursor->GetOwner()))) {
return NS_ERROR_FAILURE;
// Push pending results in reversed order.
pending.SetCapacity(pending.Length() + aSize);
while (aSize) {
--aSize;
pending.AppendElement(aResults[aSize]);
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> wrappedResult(cx);
nsresult rv = nsContentUtils::WrapNative(cx, aResult, &wrappedResult);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = mDOMCursor->FireSuccessWithNextPendingResult();
if (NS_FAILED(rv)) {
NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR);
}
mDOMCursor->FireSuccess(wrappedResult);
return NS_OK;
}

View File

@ -6,6 +6,8 @@
#ifndef mozilla_dom_mobilemessage_MobileMessageCursorCallback_h
#define mozilla_dom_mobilemessage_MobileMessageCursorCallback_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/DOMCursor.h"
#include "nsIMobileMessageCursorCallback.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
@ -16,12 +18,46 @@ class nsICursorContinueCallback;
namespace mozilla {
namespace dom {
class DOMCursor;
class MobileMessageManager;
namespace mobilemessage {
class MobileMessageCursorCallback;
} // namespace mobilemessage
class MobileMessageCursorCallback : public nsIMobileMessageCursorCallback
class MobileMessageCursor MOZ_FINAL : public DOMCursor
{
friend class mobilemessage::MobileMessageCursorCallback;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MobileMessageCursor, DOMCursor)
MobileMessageCursor(nsPIDOMWindow* aWindow,
nsICursorContinueCallback* aCallback);
// Override XPIDL continue function to suppress -Werror,-Woverloaded-virtual.
NS_IMETHOD
Continue(void) MOZ_OVERRIDE;
virtual void
Continue(ErrorResult& aRv) MOZ_OVERRIDE;
private:
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
~MobileMessageCursor() {}
private:
// List of read-ahead results in reversed order.
nsTArray<nsCOMPtr<nsISupports>> mPendingResults;
nsresult
FireSuccessWithNextPendingResult();
};
namespace mobilemessage {
class MobileMessageCursorCallback MOZ_FINAL : public nsIMobileMessageCursorCallback
{
friend class mozilla::dom::MobileMessageManager;
@ -37,12 +73,13 @@ public:
}
private:
virtual ~MobileMessageCursorCallback()
// MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
~MobileMessageCursorCallback()
{
MOZ_COUNT_DTOR(MobileMessageCursorCallback);
}
nsRefPtr<DOMCursor> mDOMCursor;
nsRefPtr<MobileMessageCursor> mDOMCursor;
};
} // namespace mobilemessage

View File

@ -439,9 +439,10 @@ MobileMessageManager::GetMessages(const MobileMessageFilter& aFilter,
return nullptr;
}
cursorCallback->mDOMCursor = new DOMCursor(GetOwner(), continueCallback);
cursorCallback->mDOMCursor =
new MobileMessageCursor(GetOwner(), continueCallback);
nsRefPtr<DOMCursor> cursor = cursorCallback->mDOMCursor;
nsRefPtr<DOMCursor> cursor(cursorCallback->mDOMCursor);
return cursor.forget();
}
@ -491,9 +492,10 @@ MobileMessageManager::GetThreads(ErrorResult& aRv)
return nullptr;
}
cursorCallback->mDOMCursor = new DOMCursor(GetOwner(), continueCallback);
cursorCallback->mDOMCursor =
new MobileMessageCursor(GetOwner(), continueCallback);
nsRefPtr<DOMCursor> cursor = cursorCallback->mDOMCursor;
nsRefPtr<DOMCursor> cursor(cursorCallback->mDOMCursor);
return cursor.forget();
}

View File

@ -65,6 +65,9 @@ const COLLECT_ID_END = 0;
const COLLECT_ID_ERROR = -1;
const COLLECT_TIMESTAMP_UNUSED = 0;
// Default value for integer preference "dom.sms.maxReadAheadEntries".
const DEFAULT_READ_AHEAD_ENTRIES = 7;
XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
"@mozilla.org/mobilemessage/mobilemessageservice;1",
"nsIMobileMessageService");
@ -3143,7 +3146,7 @@ MobileMessageDB.prototype = {
let self = this;
self.newTxn(READ_ONLY, function(error, txn, stores) {
let collector = cursor.collector;
let collector = cursor.collector.idCollector;
let collect = collector.collect.bind(collector);
FilterSearcherHelper.transact(self, txn, error, filter, aReverse, collect);
}, [MESSAGE_STORE_NAME, PARTICIPANT_STORE_NAME]);
@ -3252,7 +3255,7 @@ MobileMessageDB.prototype = {
let cursor = new GetThreadsCursor(this, callback);
this.newTxn(READ_ONLY, function(error, txn, threadStore) {
let collector = cursor.collector;
let collector = cursor.collector.idCollector;
if (error) {
collector.collect(null, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
return;
@ -3489,11 +3492,306 @@ let FilterSearcherHelper = {
}
};
function ResultsCollector() {
/**
* Collector class for read-ahead result objects. Mmdb may now try to fetch
* message/thread records before it's requested explicitly.
*
* The read ahead behavior can be controlled by an integer mozSettings entry
* "ril.sms.maxReadAheadEntries" as well as an integer holding preference
* "dom.sms.maxReadAheadEntries". The meanings are:
*
* positive: finite read-ahead entries,
* 0: don't read ahead unless explicitly requested, (default)
* negative: read ahead all IDs if possible.
*
* The order of ID filtering objects are now:
*
* [UnionResultsCollector]
* +-> [IntersectionResultsCollector]
* +-> IDsCollector
* +-> ResultsCollector
*
* ResultsCollector has basically similar behaviour with IDsCollector. When
* RC::squeeze() is called, either RC::drip() is called instantly if we have
* already fetched results available, or the request is kept and IC::squeeze()
* is called.
*
* When RC::collect is called by IC::drip, it proceeds to fetch the
* corresponding record given that collected ID is neither an error nor an end
* mark. After the message/thread record being fetched, ResultsCollector::drip
* is called if we have pending request. Anyway, RC::maybeSqueezeIdCollector is
* called to determine whether we need to call IC::squeeze again.
*
* RC::squeeze is called when nsICursorContinueCallback::handleContinue() is
* called. ResultsCollector::drip will call to
* nsIMobileMessageCursorCallback::notifyFoo.
*
* In summary, the major call paths are:
*
* RC::squeeze
* o-> RC::drip
* +-> RC::notifyCallback
* +-> nsIMobileMessageCursorCallback::notifyFoo
* +-> RC::maybeSqueezeIdCollector
* o-> IC::squeeze
* o-> IC::drip
* +-> RC::collect
* o-> RC::readAhead
* +-> RC::notifyResult
* o-> RC::drip ...
* +-> RC::maybeSqueezeIdCollector ...
* o-> RC::notifyResult ...
*/
function ResultsCollector(readAheadFunc) {
this.idCollector = new IDsCollector();
this.results = [];
this.readAhead = readAheadFunc;
this.maxReadAhead = DEFAULT_READ_AHEAD_ENTRIES;
try {
// positive: finite read-ahead entries,
// 0: don't read ahead unless explicitly requested,
// negative: read ahead all IDs if possible.
this.maxReadAhead =
Services.prefs.getIntPref("dom.sms.maxReadAheadEntries");
} catch (e) {}
}
ResultsCollector.prototype = {
/**
* Underlying ID collector object.
*/
idCollector: null,
/**
* An array keeping fetched result objects. Replaced by a new empty array
* every time when |this.drip| is called.
*/
results: null,
/**
* A function that takes (<txn>, <id>, <collector>). It fetches the object
* specified by <id> and notify <collector> with that by calling
* |<collector>.notifyResult()|. If <txn> is null, this function should
* create a new read-only transaction itself. The returned result object may
* be null to indicate an error during the fetch process.
*/
readAhead: null,
/**
* A boolean value inidicating a readAhead call is ongoing. Set before calling
* |this.readAhead| and reset in |this.notifyResult|.
*/
readingAhead: false,
/**
* A numeric value read from preference "dom.sms.maxReadAheadEntries".
*/
maxReadAhead: 0,
/**
* An active IDBTransaction object to be reused.
*/
activeTxn: null,
/**
* A nsIMobileMessageCursorCallback.
*/
requestWaiting: null,
/**
* A boolean value indicating either a COLLECT_ID_END or COLLECT_ID_ERROR has
* been received.
*/
done: false,
/**
* When |this.done|, it's either COLLECT_ID_END or COLLECT_ID_ERROR.
*/
lastId: null,
/**
* Receive collected id from IDsCollector and fetch the correspond result
* object if necessary.
*
* @param txn
* An IDBTransaction object. Null if there is no active transaction in
* IDsCollector. That is, the ID collecting transaction is completed.
* @param id
* A positive numeric id, COLLECT_ID_END(0), or COLLECT_ID_ERROR(-1).
*/
collect: function(txn, id) {
if (this.done) {
// If this callector has been terminated because of previous errors in
// |this.readAhead|, ignore any further IDs from IDsCollector.
return;
}
if (DEBUG) debug("ResultsCollector::collect ID = " + id);
// Reuse the active transaction cached if IDsCollector has no active
// transaction.
txn = txn || this.activeTxn;
if (id > 0) {
this.readingAhead = true;
this.readAhead(txn, id, this);
} else {
this.notifyResult(txn, id, null);
}
},
/**
* Callback function for |this.readAhead|.
*
* This function pushes result object to |this.results| or updates
* |this.done|, |this.lastId| if an end mark or an error is found. Since we
* have already a valid result entry, check |this.requestWaiting| and deal
* with it. At last, call to |this.maybeSqueezeIdCollector| to ask more id
* again if necessary.
*
* @param txn
* An IDBTransaction object. Null if caller has no active transaction.
* @param id
* A positive numeric id, COLLECT_ID_END(0), or COLLECT_ID_ERROR(-1).
* @param result
* An object associated with id. Null if |this.readAhead| failed.
*/
notifyResult: function(txn, id, result) {
if (DEBUG) debug("notifyResult(txn, " + id + ", <result>)");
this.readingAhead = false;
if (id > 0) {
if (result != null) {
this.results.push(result);
} else {
id = COLLECT_ID_ERROR;
}
}
if (id <= 0) {
this.lastId = id;
this.done = true;
}
if (!this.requestWaiting) {
if (DEBUG) debug("notifyResult: cursor.continue() not called yet");
} else {
let callback = this.requestWaiting;
this.requestWaiting = null;
this.drip(callback);
}
this.maybeSqueezeIdCollector(txn);
},
/**
* Request for one more ID if necessary.
*
* @param txn
* An IDBTransaction object. Null if caller has no active transaction.
*/
maybeSqueezeIdCollector: function(txn) {
if (this.done || // Nothing to be read.
this.readingAhead || // Already in progress.
this.idCollector.requestWaiting) { // Already requested.
return;
}
let max = this.maxReadAhead;
if (!max && this.requestWaiting) {
// If |this.requestWaiting| is set, try to read ahead at least once.
max = 1;
}
if (max >= 0 && this.results.length >= max) {
// More-equal than <max> entries has been read. Stop.
if (DEBUG) debug("maybeSqueezeIdCollector: max " + max + " entries read. Stop.");
return;
}
// A hack to pass current txn to |this.collect| when it's called directly by
// |IDsCollector.squeeze|.
this.activeTxn = txn;
this.idCollector.squeeze(this.collect.bind(this));
this.activeTxn = null;
},
/**
* Request to pass available results or wait.
*
* @param callback
* A nsIMobileMessageCursorCallback.
*/
squeeze: function(callback) {
if (this.requestWaiting) {
throw new Error("Already waiting for another request!");
}
if (this.results.length || this.done) {
// If |this.results.length| is non-zero, we have already some results to
// pass. Otherwise, if |this.done| evaluates to true, we have also a
// confirmed result to pass.
this.drip(callback);
} else {
this.requestWaiting = callback;
}
// If we called |this.drip| in the last step, the fetched results have been
// consumed and we should ask some more for read-ahead now.
//
// Otherwise, kick start read-ahead again because it may be stopped
// previously because of |this.maxReadAhead| had been reached.
this.maybeSqueezeIdCollector(null);
},
/**
* Consume fetched resutls.
*
* @param callback
* A nsIMobileMessageCursorCallback.
*/
drip: function(callback) {
let results = this.results;
this.results = [];
let func = this.notifyCallback.bind(this, callback, results, this.lastId);
Services.tm.currentThread.dispatch(func, Ci.nsIThread.DISPATCH_NORMAL);
},
/**
* Notify a nsIMobileMessageCursorCallback.
*
* @param callback
* A nsIMobileMessageCursorCallback.
* @param results
* An array of result objects.
* @param lastId
* Since we only call |this.drip| when either there are results
* available or the read-ahead has done, so lastId here will be
* COLLECT_ID_END or COLLECT_ID_ERROR when results is empty and null
* otherwise.
*/
notifyCallback: function(callback, results, lastId) {
if (DEBUG) {
debug("notifyCallback(results[" + results.length + "], " + lastId + ")");
}
if (results.length) {
callback.notifyCursorResult(results, results.length);
} else if (lastId == COLLECT_ID_END) {
callback.notifyCursorDone();
} else {
callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
}
}
};
function IDsCollector() {
this.results = [];
this.done = false;
}
ResultsCollector.prototype = {
IDsCollector.prototype = {
results: null,
requestWaiting: null,
done: null,
@ -3517,20 +3815,16 @@ ResultsCollector.prototype = {
return false;
}
if (DEBUG) {
debug("collect: message ID = " + id);
}
if (id) {
// Queue up any id but '0' and replies later accordingly.
this.results.push(id);
}
if (DEBUG) debug("IDsCollector::collect ID = " + id);
// Queue up any id.
this.results.push(id);
if (id <= 0) {
// No more processing on '0' or negative values passed.
this.done = true;
}
if (!this.requestWaiting) {
if (DEBUG) debug("Cursor.continue() not called yet");
if (DEBUG) debug("IDsCollector::squeeze() not called yet");
return !this.done;
}
@ -3575,22 +3869,11 @@ ResultsCollector.prototype = {
* A callback function that accepts a numeric id.
*/
drip: function(txn, callback) {
if (!this.results.length) {
if (DEBUG) debug("No messages matching the filter criteria");
callback(txn, COLLECT_ID_END);
return;
let firstId = this.results[0];
if (firstId > 0) {
this.results.shift();
}
if (this.results[0] < 0) {
// An previous error found. Keep the answer in results so that we can
// reply INTERNAL_ERROR for further requests.
if (DEBUG) debug("An previous error found");
callback(txn, COLLECT_ID_ERROR);
return;
}
let firstMessageId = this.results.shift();
callback(txn, firstMessageId);
callback(txn, firstId);
}
};
@ -3784,7 +4067,7 @@ UnionResultsCollector.prototype = {
function GetMessagesCursor(mmdb, callback) {
this.mmdb = mmdb;
this.callback = callback;
this.collector = new ResultsCollector();
this.collector = new ResultsCollector(this.getMessage.bind(this));
this.handleContinue(); // Trigger first run.
}
@ -3796,7 +4079,7 @@ GetMessagesCursor.prototype = {
callback: null,
collector: null,
getMessageTxn: function(messageStore, messageId) {
getMessageTxn: function(txn, messageStore, messageId, collector) {
if (DEBUG) debug ("Fetching message " + messageId);
let getRequest = messageStore.get(messageId);
@ -3807,32 +4090,26 @@ GetMessagesCursor.prototype = {
}
let domMessage =
self.mmdb.createDomMessageFromRecord(event.target.result);
self.callback.notifyCursorResult(domMessage);
collector.notifyResult(txn, messageId, domMessage);
};
getRequest.onerror = function(event) {
// Error reporting is done in ResultsCollector.notifyCallback.
event.stopPropagation();
event.preventDefault();
if (DEBUG) {
debug("notifyCursorError - messageId: " + messageId);
}
self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
collector.notifyResult(txn, messageId, null);
};
},
notify: function(txn, messageId) {
if (!messageId) {
this.callback.notifyCursorDone();
return;
}
if (messageId < 0) {
this.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
}
getMessage: function(txn, messageId, collector) {
// When filter transaction is not yet completed, we're called with current
// ongoing transaction object.
if (txn) {
let messageStore = txn.objectStore(MESSAGE_STORE_NAME);
this.getMessageTxn(messageStore, messageId);
this.getMessageTxn(txn, messageStore, messageId, collector);
return;
}
@ -3840,10 +4117,11 @@ GetMessagesCursor.prototype = {
let self = this;
this.mmdb.newTxn(READ_ONLY, function(error, txn, messageStore) {
if (error) {
self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
debug("getMessage: failed to create new transaction");
collector.notifyResult(null, messageId, null);
} else {
self.getMessageTxn(txn, messageStore, messageId, collector);
}
self.getMessageTxn(messageStore, messageId);
}, [MESSAGE_STORE_NAME]);
},
@ -3851,14 +4129,14 @@ GetMessagesCursor.prototype = {
handleContinue: function() {
if (DEBUG) debug("Getting next message in list");
this.collector.squeeze(this.notify.bind(this));
this.collector.squeeze(this.callback);
}
};
function GetThreadsCursor(mmdb, callback) {
this.mmdb = mmdb;
this.callback = callback;
this.collector = new ResultsCollector();
this.collector = new ResultsCollector(this.getThread.bind(this));
this.handleContinue(); // Trigger first run.
}
@ -3870,11 +4148,10 @@ GetThreadsCursor.prototype = {
callback: null,
collector: null,
getThreadTxn: function(threadStore, threadId) {
getThreadTxn: function(txn, threadStore, threadId, collector) {
if (DEBUG) debug ("Fetching thread " + threadId);
let getRequest = threadStore.get(threadId);
let self = this;
getRequest.onsuccess = function(event) {
let threadRecord = event.target.result;
if (DEBUG) {
@ -3888,32 +4165,26 @@ GetThreadsCursor.prototype = {
threadRecord.body,
threadRecord.unreadCount,
threadRecord.lastMessageType);
self.callback.notifyCursorResult(thread);
collector.notifyResult(txn, threadId, thread);
};
getRequest.onerror = function(event) {
// Error reporting is done in ResultsCollector.notifyCallback.
event.stopPropagation();
event.preventDefault();
if (DEBUG) {
debug("notifyCursorError - threadId: " + threadId);
}
self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
collector.notifyResult(txn, threadId, null);
};
},
notify: function(txn, threadId) {
if (!threadId) {
this.callback.notifyCursorDone();
return;
}
if (threadId < 0) {
this.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
}
getThread: function(txn, threadId, collector) {
// When filter transaction is not yet completed, we're called with current
// ongoing transaction object.
if (txn) {
let threadStore = txn.objectStore(THREAD_STORE_NAME);
this.getThreadTxn(threadStore, threadId);
this.getThreadTxn(txn, threadStore, threadId, collector);
return;
}
@ -3921,10 +4192,10 @@ GetThreadsCursor.prototype = {
let self = this;
this.mmdb.newTxn(READ_ONLY, function(error, txn, threadStore) {
if (error) {
self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
return;
collector.notifyResult(null, threadId, null);
} else {
self.getThreadTxn(txn, threadStore, threadId, collector);
}
self.getThreadTxn(threadStore, threadId);
}, [THREAD_STORE_NAME]);
},
@ -3932,7 +4203,7 @@ GetThreadsCursor.prototype = {
handleContinue: function() {
if (DEBUG) debug("Getting next thread in list");
this.collector.squeeze(this.notify.bind(this));
this.collector.squeeze(this.callback);
}
}

View File

@ -4,10 +4,11 @@
#include "nsISupports.idl"
[scriptable, builtinclass, uuid(8fd0dba2-032e-4190-a751-07cc3782e93e)]
[scriptable, builtinclass, uuid(134a6958-543b-46e2-b419-4631a2314164)]
interface nsIMobileMessageCursorCallback : nsISupports
{
void notifyCursorError(in long error);
void notifyCursorResult(in nsISupports result);
void notifyCursorResult([array, size_is(size)] in nsISupports results,
in uint32_t size);
void notifyCursorDone();
};

View File

@ -293,22 +293,17 @@ MobileMessageCursorChild::RecvNotifyResult(const MobileMessageCursorData& aData)
{
MOZ_ASSERT(mCursorCallback);
nsCOMPtr<nsISupports> result;
switch(aData.type()) {
case MobileMessageCursorData::TMmsMessageData:
result = new MmsMessage(aData.get_MmsMessageData());
case MobileMessageCursorData::TMobileMessageArrayData:
DoNotifyResult(aData.get_MobileMessageArrayData().messages());
break;
case MobileMessageCursorData::TSmsMessageData:
result = new SmsMessage(aData.get_SmsMessageData());
break;
case MobileMessageCursorData::TThreadData:
result = new MobileMessageThread(aData.get_ThreadData());
case MobileMessageCursorData::TThreadArrayData:
DoNotifyResult(aData.get_ThreadArrayData().threads());
break;
default:
MOZ_CRASH("Received invalid response parameters!");
}
mCursorCallback->NotifyCursorResult(result);
return true;
}
@ -338,6 +333,48 @@ MobileMessageCursorChild::HandleContinue()
return NS_OK;
}
void
MobileMessageCursorChild::DoNotifyResult(const nsTArray<MobileMessageData>& aDataArray)
{
const uint32_t length = aDataArray.Length();
MOZ_ASSERT(length);
AutoFallibleTArray<nsISupports*, 1> autoArray;
NS_ENSURE_TRUE_VOID(autoArray.SetCapacity(length));
AutoFallibleTArray<nsCOMPtr<nsISupports>, 1> messages;
NS_ENSURE_TRUE_VOID(messages.SetCapacity(length));
for (uint32_t i = 0; i < length; i++) {
nsCOMPtr<nsISupports> message = CreateMessageFromMessageData(aDataArray[i]);
NS_ENSURE_TRUE_VOID(messages.AppendElement(message));
NS_ENSURE_TRUE_VOID(autoArray.AppendElement(message.get()));
}
mCursorCallback->NotifyCursorResult(autoArray.Elements(), length);
}
void
MobileMessageCursorChild::DoNotifyResult(const nsTArray<ThreadData>& aDataArray)
{
const uint32_t length = aDataArray.Length();
MOZ_ASSERT(length);
AutoFallibleTArray<nsISupports*, 1> autoArray;
NS_ENSURE_TRUE_VOID(autoArray.SetCapacity(length));
AutoFallibleTArray<nsCOMPtr<nsISupports>, 1> threads;
NS_ENSURE_TRUE_VOID(threads.SetCapacity(length));
for (uint32_t i = 0; i < length; i++) {
nsCOMPtr<nsISupports> thread = new MobileMessageThread(aDataArray[i]);
NS_ENSURE_TRUE_VOID(threads.AppendElement(thread));
NS_ENSURE_TRUE_VOID(autoArray.AppendElement(thread.get()));
}
mCursorCallback->NotifyCursorResult(autoArray.Elements(), length);
}
} // namespace mobilemessage
} // namespace dom
} // namespace mozilla

View File

@ -129,6 +129,13 @@ protected:
virtual bool
Recv__delete__(const int32_t& aError) MOZ_OVERRIDE;
private:
void
DoNotifyResult(const nsTArray<MobileMessageData>& aData);
void
DoNotifyResult(const nsTArray<ThreadData>& aData);
};
} // namespace mobilemessage

View File

@ -843,40 +843,59 @@ MobileMessageCursorParent::NotifyCursorError(int32_t aError)
}
NS_IMETHODIMP
MobileMessageCursorParent::NotifyCursorResult(nsISupports* aResult)
MobileMessageCursorParent::NotifyCursorResult(nsISupports** aResults,
uint32_t aSize)
{
MOZ_ASSERT(aResults && *aResults && aSize);
// The child process could die before this asynchronous notification, in which
// case ActorDestroy() was called and mContinueCallback is now null. Return an
// error here to avoid sending a message to the dead process.
NS_ENSURE_TRUE(mContinueCallback, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMMozSmsMessage> iSms = do_QueryInterface(aResult);
if (iSms) {
SmsMessage* message = static_cast<SmsMessage*>(aResult);
return SendNotifyResult(MobileMessageCursorData(message->GetData()))
? NS_OK : NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMMozMmsMessage> iMms = do_QueryInterface(aResult);
if (iMms) {
MmsMessage* message = static_cast<MmsMessage*>(aResult);
ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager());
MmsMessageData data;
if (!message->GetData(parent, data)) {
return NS_ERROR_FAILURE;
}
return SendNotifyResult(MobileMessageCursorData(data))
? NS_OK : NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMMozMobileMessageThread> iThread = do_QueryInterface(aResult);
nsCOMPtr<nsIDOMMozMobileMessageThread> iThread =
do_QueryInterface(aResults[0]);
if (iThread) {
MobileMessageThread* thread = static_cast<MobileMessageThread*>(aResult);
return SendNotifyResult(MobileMessageCursorData(thread->GetData()))
nsTArray<ThreadData> threads;
for (uint32_t i = 0; i < aSize; i++) {
nsCOMPtr<nsIDOMMozMobileMessageThread> iThread =
do_QueryInterface(aResults[i]);
NS_ENSURE_TRUE(iThread, NS_ERROR_FAILURE);
MobileMessageThread* thread =
static_cast<MobileMessageThread*>(iThread.get());
threads.AppendElement(thread->GetData());
}
return SendNotifyResult(MobileMessageCursorData(ThreadArrayData(threads)))
? NS_OK : NS_ERROR_FAILURE;
}
MOZ_CRASH("Received invalid response parameters!");
ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager());
nsTArray<MobileMessageData> messages;
for (uint32_t i = 0; i < aSize; i++) {
nsCOMPtr<nsIDOMMozSmsMessage> iSms = do_QueryInterface(aResults[i]);
if (iSms) {
SmsMessage* sms = static_cast<SmsMessage*>(iSms.get());
messages.AppendElement(sms->GetData());
continue;
}
nsCOMPtr<nsIDOMMozMmsMessage> iMms = do_QueryInterface(aResults[i]);
if (iMms) {
MmsMessage* mms = static_cast<MmsMessage*>(iMms.get());
MmsMessageData mmsData;
NS_ENSURE_TRUE(mms->GetData(parent, mmsData), NS_ERROR_FAILURE);
messages.AppendElement(mmsData);
continue;
}
return NS_ERROR_FAILURE;
}
return SendNotifyResult(MobileMessageCursorData(MobileMessageArrayData(messages)))
? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP

View File

@ -99,11 +99,20 @@ struct ThreadData
MessageType lastMessageType;
};
struct MobileMessageArrayData
{
MobileMessageData[] messages;
};
struct ThreadArrayData
{
ThreadData[] threads;
};
union MobileMessageCursorData
{
MmsMessageData;
SmsMessageData;
ThreadData;
MobileMessageArrayData;
ThreadArrayData;
};
struct DeletedMessageInfoData

View File

@ -303,9 +303,9 @@ function createMmdbCursor(aMmdb, aMethodName) {
deferred.reject([aRv, results]);
},
notifyCursorResult: function(aResult) {
ok(true, "notifyCursorResult: " + aResult.id);
results.push(aResult);
notifyCursorResult: function(aResults, aSize) {
ok(true, "notifyCursorResult: " + aResults.map(function(aElement) { return aElement.id; }));
results = results.concat(aResults);
cursor.handleContinue();
},

View File

@ -410,8 +410,6 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
CheckClassInitialized();
nsRefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
if (!plugin)
return NS_ERROR_OUT_OF_MEMORY;
PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
if (!pluginLib) {
@ -421,6 +419,7 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
#if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
if (!pluginLib->HasRequiredFunctions()) {
NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
delete pluginLib;
return NS_ERROR_FAILURE;
}
#endif
@ -866,7 +865,7 @@ _geturl(NPP npp, const char* relativeURL, const char* target)
(strncmp(relativeURL, "ftp:", 4) != 0)) {
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
const char *name = nullptr;
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
host->GetPluginName(inst, &name);
@ -2096,14 +2095,14 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
#ifndef NP_NO_QUICKDRAW
case NPNVsupportsQuickDrawBool: {
*(NPBool*)result = false;
return NPERR_NO_ERROR;
}
#endif
case NPNVsupportsCoreGraphicsBool: {
*(NPBool*)result = true;
return NPERR_NO_ERROR;
}
@ -2173,14 +2172,14 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
InitMatrixInterface(i);
return NPERR_NO_ERROR;
}
case kPathInterfaceV0_ANPGetValue: {
LOG("get path interface");
ANPPathInterfaceV0 *i = (ANPPathInterfaceV0 *) result;
InitPathInterface(i);
return NPERR_NO_ERROR;
}
case kTypefaceInterfaceV0_ANPGetValue: {
LOG("get typeface interface");
ANPTypefaceInterfaceV0 *i = (ANPTypefaceInterfaceV0 *) result;
@ -2236,7 +2235,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
InitSurfaceInterface(i);
return NPERR_NO_ERROR;
}
case kSupportedDrawingModel_ANPGetValue: {
LOG("get supported drawing model");
uint32_t* bits = reinterpret_cast<uint32_t*>(result);

View File

@ -6,7 +6,7 @@
FAIL_ON_WARNINGS = True
PROGRAM = 'plugin-hang-ui'
Program('plugin-hang-ui')
UNIFIED_SOURCES += [
'MiniShmChild.cpp',

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'plugin_child_interpose'
SharedLibrary('plugin_child_interpose')
UNIFIED_SOURCES += [ "%s.mm" % (LIBRARY_NAME) ]
@ -12,6 +12,4 @@ UNIFIED_SOURCES += [
'plugin_child_quirks.mm',
]
FORCE_SHARED_LIB = True
OS_LIBS += ['-framework Carbon']

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'nptestjava'
SharedLibrary('nptestjava')
relative_path = '..'
include('../testplugin.mozbuild')

View File

@ -6,7 +6,7 @@
DIRS += ['secondplugin', 'javaplugin']
LIBRARY_NAME = 'nptest'
SharedLibrary('nptest')
FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']

View File

@ -4,7 +4,7 @@
# 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/.
LIBRARY_NAME = 'npsecondtest'
SharedLibrary('npsecondtest')
relative_path = '..'
include('../testplugin.mozbuild')

View File

@ -40,8 +40,6 @@ elif toolkit == 'windows':
'msimg32',
]
FORCE_SHARED_LIB = True
# must link statically with the CRT; nptest isn't Gecko code
USE_STATIC_LIBS = True

View File

@ -284,8 +284,8 @@ function RILContentHelper() {
this.voicemailStatuses = [];
for (let clientId = 0; clientId < this.numClients; clientId++) {
this.rilContexts[clientId] = {
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
iccInfo: null
cardState: Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
iccInfo: null
};
this.voicemailInfos[clientId] = new VoicemailInfo();

View File

@ -559,8 +559,8 @@ XPCOMUtils.defineLazyGetter(this, "gRadioEnabledController", function() {
_isCardPresentAtClient: function(clientId) {
let cardState = _ril.getRadioInterface(clientId).rilContext.cardState;
return cardState !== RIL.GECKO_CARDSTATE_UNDETECTED &&
cardState !== RIL.GECKO_CARDSTATE_UNKNOWN;
return cardState !== Ci.nsIIccProvider.CARD_STATE_UNDETECTED &&
cardState !== Ci.nsIIccProvider.CARD_STATE_UNKNOWN;
},
_isRadioAbleToEnableAtClient: function(clientId, numCards) {
@ -1873,7 +1873,7 @@ function RadioInterface(aClientId, aWorkerMessenger) {
aWorkerMessenger.registerClient(aClientId, this);
this.rilContext = {
cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
cardState: Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
iccInfo: null,
imsi: null
};
@ -3713,7 +3713,7 @@ RadioInterface.prototype = {
} else if (radioState == RIL.GECKO_RADIOSTATE_DISABLED) {
if (DEBUG) this.debug("Error! Radio is disabled when sending SMS.");
errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
} else if (this.rilContext.cardState != "ready") {
} else if (this.rilContext.cardState != Ci.nsIIccProvider.CARD_STATE_READY) {
if (DEBUG) this.debug("Error! SIM card is not ready when sending SMS.");
errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
}

View File

@ -2487,38 +2487,40 @@ this.GECKO_RADIOSTATE_ENABLED = "enabled";
this.GECKO_RADIOSTATE_DISABLING = "disabling";
this.GECKO_RADIOSTATE_DISABLED = "disabled";
this.GECKO_CARDSTATE_UNINITIALIZED = "uninitialized";
this.GECKO_CARDSTATE_UNDETECTED = null;
this.GECKO_CARDSTATE_ILLEGAL = "illegal";
this.GECKO_CARDSTATE_UNKNOWN = "unknown";
this.GECKO_CARDSTATE_PIN_REQUIRED = "pinRequired";
this.GECKO_CARDSTATE_PUK_REQUIRED = "pukRequired";
this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = "personalizationInProgress";
this.GECKO_CARDSTATE_PERSONALIZATION_READY = "personalizationReady";
this.GECKO_CARDSTATE_NETWORK_LOCKED = "networkLocked";
this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = "networkSubsetLocked";
this.GECKO_CARDSTATE_NETWORK1_LOCKED = "network1Locked";
this.GECKO_CARDSTATE_NETWORK2_LOCKED = "network2Locked";
this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = "hrpdNetworkLocked";
this.GECKO_CARDSTATE_CORPORATE_LOCKED = "corporateLocked";
this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = "serviceProviderLocked";
this.GECKO_CARDSTATE_SIM_LOCKED = "simPersonalizationLock";
this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = "ruimCorporateLocked";
this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = "ruimServiceProviderLocked";
this.GECKO_CARDSTATE_RUIM_LOCKED = "ruimPersonalizationLock";
this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = "networkPukRequired";
this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = "networkSubsetPukRequired";
this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = "network1PukRequired";
this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = "network2PukRequired";
this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = "hrpdNetworkPukRequired";
this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = "corporatePukRequired";
this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = "serviceProviderPukRequired";
this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = "simPersonalizationPukRequired";
this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = "ruimCorporatePukRequired";
this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = "ruimServiceProviderPukRequired";
this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = "ruimPersonalizationPukRequired";
this.GECKO_CARDSTATE_READY = "ready";
this.GECKO_CARDSTATE_PERMANENT_BLOCKED = "permanentBlocked";
// Only used in ril_worker.js
this.GECKO_CARDSTATE_UNINITIALIZED = 4294967294; // UINT32_MAX - 1
// See nsIIccProvider::CARD_STATE_*
this.GECKO_CARDSTATE_UNDETECTED = 4294967295; // UINT32_MAX
this.GECKO_CARDSTATE_UNKNOWN = 0;
this.GECKO_CARDSTATE_READY = 1;
this.GECKO_CARDSTATE_PIN_REQUIRED = 2;
this.GECKO_CARDSTATE_PUK_REQUIRED = 3;
this.GECKO_CARDSTATE_PERMANENT_BLOCKED = 4;
this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = 5;
this.GECKO_CARDSTATE_PERSONALIZATION_READY = 6;
this.GECKO_CARDSTATE_NETWORK_LOCKED = 7;
this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = 8;
this.GECKO_CARDSTATE_CORPORATE_LOCKED = 9;
this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = 10;
this.GECKO_CARDSTATE_SIM_LOCKED = 11;
this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = 12;
this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = 14;
this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = 16;
this.GECKO_CARDSTATE_NETWORK1_LOCKED = 17;
this.GECKO_CARDSTATE_NETWORK2_LOCKED = 18;
this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = 19;
this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = 20;
this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
this.GECKO_CARDSTATE_RUIM_LOCKED = 22;
this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = 23;
this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = 24;
this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = 25;
this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = 28;
this.GECKO_CARDSTATE_ILLEGAL = 29;
this.GECKO_CARDLOCK_PIN = "pin";
this.GECKO_CARDLOCK_PIN2 = "pin2";
@ -2556,6 +2558,7 @@ PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_PUK] = GECKO_CARDSTATE_NETWORK_PUK
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK] = GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK] = GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM_PUK] = GECKO_CARDSTATE_SIM_PUK_REQUIRED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1] = GECKO_CARDSTATE_NETWORK1_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2] = GECKO_CARDSTATE_NETWORK2_LOCKED;
PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD] = GECKO_CARDSTATE_HRPD_NETWORK_LOCKED;

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