Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-08-08 15:09:49 -07:00
commit 8d084d5b2e
397 changed files with 6131 additions and 2506 deletions

View File

@ -81,7 +81,7 @@ default alldep all:: $(topsrcdir)/configure config.status
$(RM) -r $(DIST)/include
$(RM) -r $(DIST)/private
$(RM) -r $(DIST)/public
$(RM) -r $(DIST)/bin/components
$(RM) $(DIST)/chrome.manifest
$(RM) -r _tests
$(topsrcdir)/configure: $(topsrcdir)/configure.in

View File

@ -61,6 +61,7 @@ let FormAssistant = {
content.setTimeout(function showIMEForSelect() {
sendAsyncMessage("Forms:Input", getJSON(evt.target));
});
this.previousTarget = evt.target;
} else if (evt.target instanceof HTMLOptionElement &&
evt.target.parentNode instanceof HTMLSelectElement) {
content.setTimeout(function showIMEForSelect() {
@ -181,9 +182,21 @@ function getJSON(element) {
// FIXME/bug 344616 is input type="number"
// Until then, let's return 'number' even if the platform returns 'text'
// Related to Bug 769352 - Implement <input type=date>
let attributeType = element.getAttribute("type") || "";
if (attributeType && attributeType.toLowerCase() === "number")
type = "number";
if (attributeType) {
var typeLowerCase = attributeType.toLowerCase();
switch (typeLowerCase) {
case "number":
case "date":
case "time":
case "datetime":
case "datetime-local":
type = typeLowerCase;
break;
}
}
return {
"type": type.toLowerCase(),

View File

@ -54,7 +54,6 @@ function getContentWindow() {
function addPermissions(urls) {
let permissions = [
'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
'websettings-read', 'websettings-readwrite',
'content-camera', 'wifi-manage', 'desktop-notification',
'geolocation', 'device-storage', 'alarms'
];

View File

@ -27,11 +27,15 @@
<script type="application/javascript">
function OpenBrowserWindowFromDockMenu() {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
dockSupport.activateApplication(true);
let win = OpenBrowserWindow();
win.addEventListener("load", function listener() {
win.removeEventListener("load", listener);
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
dockSupport.activateApplication(true);
});
return OpenBrowserWindow();
return win;
}
addEventListener("load", function() { gBrowserInit.nonBrowserWindowStartup() }, false);

View File

@ -43,11 +43,16 @@ function test_loadTabs(restoreHiddenTabs, callback) {
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
}
if (win.gBrowser.tabs.length - needsRestore == expectedTabs) {
// We're explicity checking for (isRestoring == 1) here because the test
// progress listener is called before the session store one. So when we're
// called with one tab left to restore we know that the last tab has
// finished restoring and will soon be handled by the SS listener.
let tabsNeedingRestore = win.gBrowser.tabs.length - needsRestore;
if (isRestoring == 1 && tabsNeedingRestore == expectedTabs) {
is(win.gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
TabsProgressListener.uninit();
callback();
executeSoon(callback);
}
});
}

View File

@ -58,6 +58,7 @@ else
PPL_LOCALE_ARGS=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer
endif
.DEFAULT_GOAL := installer
installer::
$(MAKE) -C .. installer-stage
$(MAKE) $(CONFIG_DIR)/setup.exe

View File

@ -154,9 +154,8 @@ libs-%:
@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) BOTH_MANIFESTS=1
@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD)
repackage-win32-installer: $(call ESCAPE_WILDCARD,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD)
@echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
@ -169,8 +168,10 @@ repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEF
$(topsrcdir)/browser/installer/windows/app.tag"
ifeq (WINNT,$(OS_ARCH))
repackage-win32-installer-%:
repackage-win32-installer-%: $(STAGEDIST)
@$(MAKE) repackage-win32-installer AB_CD=$* WIN32_INSTALLER_IN="$(WIN32_INSTALLER_IN)"
repackage-zip-%: repackage-win32-installer-%
else
repackage-win32-installer-%: ;
endif

View File

@ -36,7 +36,7 @@ TEST_DIRS += mobile/sutagent/android \
endif
ifdef MOZ_APP_BASENAME
DIST_FILES = application.ini
DIST_FILES = $(srcdir)/application.ini
ifneq (android,$(MOZ_WIDGET_TOOLKIT))
ifdef MOZ_UPDATER
@ -132,12 +132,10 @@ leaktest.py: leaktest.py.in
GARBAGE += leaktest.py
ifdef MOZ_APP_BASENAME
application.ini: application.ini.in $(APP_INI_DEPS)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
GARBAGE += application.ini
$(FINAL_TARGET)/application.ini: $(APP_INI_DEPS)
ifdef MOZ_APP_STATIC_INI
application.ini.h: appini_header.py application.ini
application.ini.h: appini_header.py $(FINAL_TARGET)/application.ini
$(PYTHON) $^ > $@
export:: application.ini.h
GARBAGE += application.ini.h

View File

@ -96,6 +96,7 @@ ifdef ENABLE_TESTS
cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py \
$(DIST_ARCH_2)/test-package-stage/reftest/; \
$(TOPSRCDIR)/build/macosx/universal/unify \
--unify-with-sort "\.manifest$$" \
--unify-with-sort "all-test-dirs\.list$$" \
$(DIST_ARCH_1)/test-package-stage \
$(DIST_ARCH_2)/test-package-stage \

View File

@ -438,7 +438,7 @@ class DeviceManager:
id - unique id of the device
uptime - uptime of the device
uptimemillis - uptime of the device in milliseconds (NOT supported on all
platforms)
implementations)
systime - system time of the device
screen - screen resolution
memory - memory stats

View File

@ -507,16 +507,11 @@ class DeviceManagerSUT(DeviceManager):
except AgentError:
return None
# wait up to 30 seconds for process to start up
timeslept = 0
while (timeslept <= 30):
process = self.processExist(appname)
if (process is not None):
break
time.sleep(3)
timeslept += 3
# The 'exec' command may wait for the process to start and end, so checking
# for the process here may result in process = None.
process = self.processExist(appname)
if (self.debug >= 4): print "got pid: %s for process: %s" % (process, appname)
return process
# external function
@ -918,7 +913,7 @@ class DeviceManagerSUT(DeviceManager):
# os - name of the os
# id - unique id of the device
# uptime - uptime of the device
# uptimemillis - uptime of the device in milliseconds
# uptimemillis - uptime of the device in milliseconds (SUTAgent 1.11+)
# systime - system time of the device
# screen - screen resolution
# rotation - rotation of the device (in degrees)

View File

@ -153,7 +153,8 @@ class RemoteAutomation(Automation):
# Setting timeout at 1 hour since on a remote device this takes much longer
self.timeout = 3600
time.sleep(15)
# The benefit of the following sleep is unclear; it was formerly 15 seconds
time.sleep(1)
@property
def pid(self):

View File

@ -59,7 +59,7 @@ public class FennecNativeActions implements Actions {
// Set up reflexive access of java classes and methods.
try {
mClassLoader = activity.getClassLoader();
mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class [] parameters = new Class[2];

View File

@ -88,7 +88,7 @@ public class FennecNativeDriver implements Driver {
// Set up reflexive access of java classes and methods.
try {
mClassLoader = activity.getClassLoader();
mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class [] parameters = new Class[2];

View File

@ -1386,7 +1386,7 @@ class _NativeWrapper(_CommandWrapper):
_CommandWrapper.__init__(self, cline, ignoreErrors, loc, context,
**kwargs)
# get the module and method to call
parts, badchar = process.clinetoargv(cline)
parts, badchar = process.clinetoargv(cline, blacklist_gray=False)
if parts is None:
raise DataError("native command '%s': shell metacharacter '%s' in command line" % (cline, badchar), self.loc)
if len(parts) < 2:

View File

@ -15,19 +15,29 @@ if sys.platform=='win32':
_log = logging.getLogger('pymake.process')
_escapednewlines = re.compile(r'\\\n')
_blacklist = re.compile(r'[$><;[~`|&()]' +
# Characters that most likely indicate a shell script and that native commands
# should reject
_blacklist = re.compile(r'[$><;\[~`|&]' +
r'|\${|(?:^|\s){(?:$|\s)') # Blacklist ${foo} and { commands }
# Characters that probably indicate a shell script, but that native commands
# shouldn't just reject
_graylist = re.compile(r'[()]')
# Characters that indicate we need to glob
_needsglob = re.compile(r'[\*\?]')
def clinetoargv(cline):
def clinetoargv(cline, blacklist_gray):
"""
If this command line can safely skip the shell, return an argv array.
@returns argv, badchar
"""
str = _escapednewlines.sub('', cline)
m = _blacklist.search(str)
if m is not None:
return None, m.group(0)
if blacklist_gray:
m = _graylist.search(str)
if m is not None:
return None, m.group(0)
args = shlex.split(str, comments=True)
@ -65,7 +75,7 @@ def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
if msys and cline.startswith('/'):
shellreason = "command starts with /"
else:
argv, badchar = clinetoargv(cline)
argv, badchar = clinetoargv(cline, blacklist_gray=True)
if argv is None:
shellreason = "command contains shell-special character '%s'" % (badchar,)
elif len(argv) and argv[0] in shellwords:

View File

@ -2,10 +2,11 @@ ifndef TOUCH
TOUCH = touch
endif
all: testfile {testfile2}
all: testfile {testfile2} (testfile3)
test -f testfile
test -f {testfile2}
test -f "(testfile3)"
@echo TEST-PASS
testfile {testfile2}:
$(TOUCH) $@
testfile {testfile2} (testfile3):
$(TOUCH) "$@"

View File

@ -107,8 +107,8 @@ netscape_security_enablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
}
static JSFunctionSpec PrivilegeManager_static_methods[] = {
{ "enablePrivilege", netscape_security_enablePrivilege, 1,0},
{nullptr,nullptr,0,0}
JS_FS("enablePrivilege", netscape_security_enablePrivilege, 1, 0),
JS_FS_END
};
/*

View File

@ -120,6 +120,17 @@ FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
ifdef _MSC_VER
ifdef .PYMAKE
PYCOMMANDPATH += $(topsrcdir)/build
CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration
CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration
else
CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
endif # .PYMAKE
endif # _MSC_VER
CC := $(CC_WRAPPER) $(CC)
CXX := $(CXX_WRAPPER) $(CXX)
MKDIR ?= mkdir
@ -562,12 +573,6 @@ export MACOSX_DEPLOYMENT_TARGET
PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
endif # MACOSX_DEPLOYMENT_TARGET
ifdef MOZ_USING_CCACHE
ifdef CLANG_CXX
export CCACHE_CPP2=1
endif
endif
ifdef MOZ_OPTIMIZE
ifeq (2,$(MOZ_OPTIMIZE))
# Only override project defaults if the config specified explicit settings
@ -576,6 +581,11 @@ endif # MOZ_OPTIMIZE=2
endif # MOZ_OPTIMIZE
endif # OS_ARCH=Darwin
ifdef MOZ_USING_CCACHE
ifdef CLANG_CXX
export CCACHE_CPP2=1
endif
endif
ifdef MOZ_NATIVE_MAKEDEPEND
MKDEPEND_DIR =

View File

@ -128,6 +128,7 @@ $(check-export-targets): $(check-export-targets-preqs)
##{ <CHECK: xpidl.mk>
check-xpidl-preqs=\
$(call mkdir_deps,$(dir-ts)) \
$(topsrcdir)/config/config.mk \
$(topsrcdir)/config/makefiles/makeutils.mk \
$(topsrcdir)/config/makefiles/xpidl.mk \
$(srcdir)/check-xpidl.mk \

View File

@ -8,6 +8,10 @@ ifdef VERBOSE
$(warning loading test)
endif
# Limit scope, we only need install_cmd= for testing
INCLUDED_AUTOCONF_MK = 1
include $(topsrcdir)/config/config.mk
USE_AUTOTARGETS_MK = 1
include $(topsrcdir)/config/makefiles/makeutils.mk
@ -21,6 +25,7 @@ XPIDLSRCS = $(srcdir)/check-xpidl.mk
include $(topsrcdir)/config/makefiles/xpidl.mk
$(call requiredfunction,topsrcdir)
$(call requiredfunction,XPIDL_GEN_DIR)

View File

@ -39,6 +39,8 @@ endif #} INCLUDED_XPIDL_MK
###########################################################################
ifdef _xpidl-todo_ #{
$(call requiredfunction,install_cmd)
## Logic batch #1
xpidl-install-src-preqs=\
$(XPIDLSRCS) \

View File

@ -1774,6 +1774,7 @@ libs export::
default all::
if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi
.DEFAULT_GOAL ?= default
#############################################################################
# Derived targets and dependencies

View File

@ -595,6 +595,7 @@ psap.h
Pt.h
pthread.h
pthread_np.h
pulse/pulseaudio.h
pwd.h
Python.h
QDOffscreen.h

View File

@ -27,6 +27,8 @@ tgts =\
$(autotgt_tests)
$(NULL)
export MAKE
export .PYMAKE
##------------------_##
##---] TARGETS [---##
@ -37,5 +39,5 @@ check:: $(tgts)
# Only run unit test when autotargets.mk is modified
$(autotgt_tests): $(topsrcdir)/config/makefiles/autotargets.mk
MAKECMD=$(MAKE) $(PYTEST) $(srcdir)/check_mkdir.tpy
$(PYTEST) $(srcdir)/check_mkdir.tpy
@$(TOUCH) $@

View File

@ -68,7 +68,7 @@ def path2posix(src):
drive = ''
winpath = src.find(':')
if -1 != winpath and 10 > winpath:
(drive, tail) = src.split(':', 2)
(drive, tail) = src.split(':', 1)
if drive:
todo = [ '', drive.rstrip(':').lstrip('/').lstrip('\\') ]
@ -98,13 +98,19 @@ def checkMkdir(work, debug=False):
logging.debug("Testing: checkMkdir")
if False:
path = os.path.abspath(__file__).split(os.sep)
# On Windows + Pymake, don't convert paths to POSIX
skipposix = sys.platform == "win32" and os.environ.get(".PYMAKE") == "1"
if skipposix:
path = os.path.abspath(__file__)
dirname_fun = os.path.dirname
else:
path = path2posix(os.path.abspath(__file__)).split('/')
root = os.path.join(os.sep, *path[:-5])
src = os.path.join(os.sep, *path[:-1])
path = path2posix(os.path.abspath(__file__))
import posixpath
dirname_fun = posixpath.dirname
src = dirname_fun(path)
# root is 5 directories up from path
root = reduce(lambda x, _: dirname_fun(x), xrange(5), path)
rootP = path2posix(root)
srcP = path2posix(src)
@ -114,37 +120,28 @@ def checkMkdir(work, debug=False):
# [0] command paths use /c/foo
# [1] os.path.exists() on mingw() requires C:\
paths = [
[ # function generated
"%s/mkdir_bycall" % (workP),
"%s/mkdir_bycall" % (work),
],
[ # explicit dependency
"%s/mkdir_bydep" % (workP),
"%s/mkdir_bydep" % (work),
],
[ # by GENERATED_DIRS macro
"%s/mkdir_bygen" % (workP),
"%s/mkdir_bygen" % (work),
]
]
"mkdir_bycall", # function generated
"mkdir_bydep", # explicit dependency
"mkdir_bygen", # by GENERATED_DIRS macro
]
## Use make from the parent "make check" call when available
cmd = { 'make': 'make' }
shell0 = os.environ.get('MAKECMD')
shell0 = os.environ.get('MAKE')
if shell0:
shell = os.path.splitext(shell0)[0] # strip: .exe, .py
if -1 != shell.find('make'):
print "MAKE COMMAND FOUND: %s" % (shell0)
cmd['make'] = path2posix(shell0)
cmd['make'] = shell0 if skipposix else path2posix(shell0)
args = []
args.append('%s' % (cmd['make']))
args.append('-C %s' % (workP))
args.append("-f %s/testor.tmpl" % (srcP))
args.append('topsrcdir=%s' % (rootP))
args.append('deps_mkdir_bycall=%s' % paths[0][0])
args.append('deps_mkdir_bydep=%s' % paths[1][0])
args.append('deps_mkdir_bygen=%s' % paths[2][0])
args.append('-C %s' % (work if skipposix else workP))
args.append("-f %s/testor.tmpl" % (src if skipposix else srcP))
args.append('topsrcdir=%s' % (root if skipposix else rootP))
args.append('deps_mkdir_bycall=%s' % paths[0])
args.append('deps_mkdir_bydep=%s' % paths[1])
args.append('deps_mkdir_bygen=%s' % paths[2])
args.append('checkup') # target
# Call will fail on mingw with output redirected ?!?
@ -160,9 +157,10 @@ def checkMkdir(work, debug=False):
raise Exception("make failed ($?=%s): cmd=%s" % (rc, cmd))
for i in paths:
logging.debug("Did testing mkdir(%s) succeed?" % (i[1]))
if not os.path.exists(i[1]):
raise Exception("Test path %s does not exist" % (i[1]))
path = os.path.join(work, i)
logging.debug("Did testing mkdir(%s) succeed?" % (path))
if not os.path.exists(path):
raise Exception("Test path %s does not exist" % (path))
def parseargs():

View File

@ -194,7 +194,7 @@ if test -n "$gonkdir" ; then
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera"
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS"
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
dnl Add -llog by default, since we use it all over the place.
LIBS="$LIBS -llog $STLPORT_LIBS"
@ -4150,6 +4150,7 @@ MOZ_SPEEX_RESAMPLER=1
MOZ_CUBEB=
MOZ_VORBIS=
MOZ_TREMOR=
MOZ_FLOATING_POINT_AUDIO=
MOZ_WAVE=1
MOZ_MEDIA=
MOZ_OPUS=1
@ -5199,6 +5200,24 @@ fi
AC_SUBST(MOZ_WEBRTC)
dnl ========================================================
dnl = Disable floating point audio.
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(floating-point,
[ --disable-floating-point Disable floating point audio],
MOZ_FLOATING_POINT_AUDIO=,
MOZ_FLOATING_POINT_AUDIO=1)
case "$target_cpu" in
arm*)
;;
*)
AC_DEFINE(MOZ_FLOATING_POINT_AUDIO)
MOZ_FLOATING_POINT_AUDIO=1
;;
esac
dnl ========================================================
dnl = Enable Raw Codecs
dnl ========================================================
@ -5227,14 +5246,6 @@ if test -n "$MOZ_OGG"; then
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
MOZ_TREMOR=1
;;
*)
MOZ_VORBIS=1
;;
esac
dnl Checks for __attribute__(aligned()) directive
AC_CACHE_CHECK([__attribute__ ((aligned ())) support],
@ -5364,14 +5375,11 @@ if test "$MOZ_WEBM"; then
MOZ_SYDNEYAUDIO=1
MOZ_CUBEB=1
MOZ_MEDIA=1
case "$target_cpu" in
arm*)
MOZ_TREMOR=1
;;
*)
if test -n "$MOZ_FLOATING_POINT_AUDIO"; then
MOZ_VORBIS=1
;;
esac
else
MOZ_TREMOR=1
fi
fi
if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then
@ -5550,6 +5558,26 @@ if test -n "$MOZ_SYDNEYAUDIO" -a "$OS_TARGET" = "Linux"; then
AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux. Disable with --disable-ogg --disable-wave --disable-webm. (On Ubuntu, you might try installing the package libasound2-dev.)])])
fi
dnl ========================================================
dnl = Enable PulseAudio
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(pulseaudio,
[ --enable-pulseaudio Enable PulseAudio support (experimental)],
MOZ_PULSEAUDIO=1,
MOZ_PULSEAUDIO=)
if test -n "$MOZ_PULSEAUDIO"; then
AC_DEFINE(MOZ_CUBEB)
PKG_CHECK_MODULES(MOZ_PULSEAUDIO, libpulse, ,
[echo "$MOZ_PULSEAUDIO_PKG_ERRORS"
AC_MSG_ERROR([pulseaudio audio backend requires libpulse package])])
fi
AC_SUBST(MOZ_PULSEAUDIO)
AC_SUBST(MOZ_PULSEAUDIO_CFLAGS)
AC_SUBST(MOZ_PULSEAUDIO_LIBS)
dnl ========================================================
dnl = Enable GStreamer
dnl ========================================================
@ -7690,9 +7718,6 @@ else
fi
AC_SUBST(CL_INCLUDES_PREFIX)
rm -f dummy-hello.c
dnl cl.py provides dependency generation for MSVC
CC_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
CXX_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
COMPILER_DEPEND=1
fi
fi
@ -7701,9 +7726,6 @@ MDDEPDIR='.deps'
AC_SUBST(MOZ_AUTO_DEPS)
AC_SUBST(COMPILER_DEPEND)
AC_SUBST(MDDEPDIR)
AC_SUBST(CC_WRAPPER)
AC_SUBST(CXX_WRAPPER)
dnl ========================================================
dnl =

View File

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DirectionalityUtils_h___
#define DirectionalityUtils_h___
class nsIContent;
class nsIDocument;
class nsINode;
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
namespace mozilla {
namespace directionality {
enum Directionality {
eDir_NotSet = 0,
eDir_RTL = 1,
eDir_LTR = 2
};
void SetDirectionality(mozilla::dom::Element* aElement, Directionality aDir,
bool aNotify = true);
/**
* Set the directionality of an element according to the algorithm defined at
* http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality,
* not including elements with auto direction.
*
* @return the directionality that the element was set to
*/
Directionality RecomputeDirectionality(mozilla::dom::Element* aElement,
bool aNotify = true);
/**
* Set the directionality of any descendants of a node that do not themselves
* have a dir attribute.
* For performance reasons we walk down the descendant tree in the rare case
* of setting the dir attribute, rather than walking up the ancestor tree in
* the much more common case of getting the element's directionality.
*/
void SetDirectionalityOnDescendants(mozilla::dom::Element* aElement,
Directionality aDir,
bool aNotify = true);
} // end namespace directionality
} // end namespace mozilla
#endif /* DirectionalityUtils_h___ */

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/FragmentOrElement.h" // for base class
#include "nsChangeHint.h" // for enum
#include "nsEventStates.h" // for member
#include "mozilla/dom/DirectionalityUtils.h"
class nsEventStateManager;
class nsFocusManager;
@ -216,6 +217,18 @@ public:
*/
virtual nsIAtom *GetClassAttributeName() const = 0;
inline mozilla::directionality::Directionality GetDirectionality() const {
if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
return mozilla::directionality::eDir_RTL;
}
if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
return mozilla::directionality::eDir_LTR;
}
return mozilla::directionality::eDir_NotSet;
}
protected:
/**
* Method to get the _intrinsic_ content state of this element. This is the

View File

@ -48,6 +48,7 @@ $(NULL)
EXPORTS_NAMESPACES = mozilla/dom mozilla
EXPORTS_mozilla/dom = \
DirectionalityUtils.h \
Element.h \
FragmentOrElement.h \
FromParser.h \

View File

@ -23,6 +23,7 @@
#include "nsPIDOMWindow.h" // for use in inline functions
#include "nsPropertyTable.h" // for member
#include "nsTHashtable.h" // for member
#include "mozilla/dom/DirectionalityUtils.h"
class imgIRequest;
class nsAString;
@ -397,6 +398,10 @@ public:
{
mBidiOptions = aBidiOptions;
}
inline mozilla::directionality::Directionality GetDocumentDirectionality() {
return mDirectionality;
}
/**
* Access HTTP header data (this may also get set from other
@ -1853,6 +1858,9 @@ protected:
// defined in nsBidiUtils.h
PRUint32 mBidiOptions;
// The root directionality of this document.
mozilla::directionality::Directionality mDirectionality;
nsCString mContentLanguage;
private:
nsCString mContentType;

View File

@ -145,8 +145,16 @@ enum {
// Set if the node has had :hover selectors matched against it
NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U,
// Set if the node has right-to-left directionality
NODE_HAS_DIRECTION_RTL = 0x00100000U,
// Set if the node has left-to-right directionality
NODE_HAS_DIRECTION_LTR = 0x00200000U,
NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL,
// Remaining bits are node type specific.
NODE_TYPE_SPECIFIC_BITS_OFFSET = 20
NODE_TYPE_SPECIFIC_BITS_OFFSET = 22
};
/**
@ -1279,6 +1287,8 @@ private:
NodeIsContent,
// Set if the node has animations or transitions
ElementHasAnimations,
// Set if node has a dir attribute with a valid value (ltr or rtl)
NodeHasValidDirAttribute,
// Guard value
BooleanFlagCount
};
@ -1346,6 +1356,9 @@ public:
void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }

View File

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */
/* 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/DirectionalityUtils.h"
#include "nsINode.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "mozilla/dom/Element.h"
#include "nsIDOMNodeFilter.h"
#include "nsTreeWalker.h"
#include "nsIDOMHTMLDocument.h"
namespace mozilla {
namespace directionality {
typedef mozilla::dom::Element Element;
void
SetDirectionality(Element* aElement, Directionality aDir, bool aNotify)
{
aElement->UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
switch (aDir) {
case eDir_RTL:
aElement->SetFlags(NODE_HAS_DIRECTION_RTL);
break;
case eDir_LTR:
aElement->SetFlags(NODE_HAS_DIRECTION_LTR);
break;
default:
break;
}
aElement->UpdateState(aNotify);
}
Directionality
RecomputeDirectionality(Element* aElement, bool aNotify)
{
Directionality dir = eDir_LTR;
if (aElement->HasValidDir()) {
dir = aElement->GetDirectionality();
} else {
Element* parent = aElement->GetElementParent();
if (parent) {
// If the element doesn't have an explicit dir attribute with a valid
// value, the directionality is the same as the parent element (but
// don't propagate the parent directionality if it isn't set yet).
Directionality parentDir = parent->GetDirectionality();
if (parentDir != eDir_NotSet) {
dir = parentDir;
}
} else {
// If there is no parent element, the directionality is the same as the
// document direction.
Directionality documentDir =
aElement->OwnerDoc()->GetDocumentDirectionality();
if (documentDir != eDir_NotSet) {
dir = documentDir;
}
}
SetDirectionality(aElement, dir, aNotify);
}
return dir;
}
void
SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
bool aNotify)
{
for (nsIContent* child = aElement->GetFirstChild(); child; ) {
if (!child->IsElement()) {
child = child->GetNextNode(aElement);
continue;
}
Element* element = child->AsElement();
if (element->HasValidDir()) {
child = child->GetNextNonChildNode(aElement);
continue;
}
SetDirectionality(element, aDir, aNotify);
child = child->GetNextNode(aElement);
}
}
} // end namespace directionality
} // end namespace mozilla

View File

@ -53,6 +53,7 @@ LOCAL_INCLUDES = \
$(NULL)
CPPSRCS = \
DirectionalityUtils.cpp \
nsAtomListUtils.cpp \
nsAttrAndChildArray.cpp \
nsAttrValue.cpp \

View File

@ -91,6 +91,7 @@
#include "nsXMLEventsManager.h"
#include "nsBidiUtils.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "nsIDOMUserDataHandler.h"
#include "nsIDOMXPathEvaluator.h"
@ -170,6 +171,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::directionality;
typedef nsTArray<Link*> LinkArray;
@ -1510,7 +1512,8 @@ nsIDocument::nsIDocument()
mAllowDNSPrefetch(true),
mIsBeingUsedAsImage(false),
mHasLinksToUpdate(false),
mPartID(0)
mPartID(0),
mDirectionality(eDir_LTR)
{
SetInDocument();
}
@ -5583,6 +5586,15 @@ nsDocument::SetDir(const nsAString& aDirection)
// No presentation; just set it on ourselves
SetBidiOptions(options);
}
Directionality dir = elt->mValue == IBMBIDI_TEXTDIRECTION_RTL ?
eDir_RTL : eDir_LTR;
SetDocumentDirectionality(dir);
// Set the directionality of the root element and its descendants, if any
Element* rootElement = GetRootElement();
if (rootElement) {
SetDirectionality(rootElement, dir, true);
SetDirectionalityOnDescendants(rootElement, dir);
}
}
break;

View File

@ -1048,6 +1048,12 @@ protected:
nsIContent* GetFirstBaseNodeWithHref();
nsresult SetFirstBaseNodeWithHref(nsIContent *node);
inline void
SetDocumentDirectionality(mozilla::directionality::Directionality aDir)
{
mDirectionality = aDir;
}
// Get the first <title> element with the given IsNodeOfType type, or
// return null if there isn't one
nsIContent* GetTitleContent(PRUint32 aNodeType);

View File

@ -51,6 +51,7 @@
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsNodeUtils.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "nsDocument.h"
#include "nsAttrValueOrString.h"
#ifdef MOZ_XUL
@ -128,6 +129,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::directionality;
nsEventStates
Element::IntrinsicState() const
@ -1358,6 +1360,13 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
SetSubtreeRootPointer(aParent->SubtreeRoot());
}
// This has to be here, rather than in nsGenericHTMLElement::BindToTree,
// because it has to happen after updating the parent pointer, but before
// recursively binding the kids.
if (IsHTML()) {
RecomputeDirectionality(this, false);
}
// If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
// that also need to be told that they are moving.
nsresult rv;
@ -1543,6 +1552,13 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
// This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
// because it has to happen after unsetting the parent pointer, but before
// recursively unbinding the kids.
if (IsHTML()) {
RecomputeDirectionality(this, false);
}
if (aDeep) {
// Do the kids. Don't call GetChildCount() here since that'll force
// XUL to generate template children, which there is no need for since

View File

@ -270,6 +270,7 @@ GK_ATOM(dialog, "dialog")
GK_ATOM(difference, "difference")
GK_ATOM(digit, "digit")
GK_ATOM(dir, "dir")
GK_ATOM(directionality, "directionality")
GK_ATOM(disableOutputEscaping, "disable-output-escaping")
GK_ATOM(disabled, "disabled")
GK_ATOM(display, "display")
@ -1758,6 +1759,7 @@ GK_ATOM(svgRadialGradientFrame, "SVGRadialGradientFrame")
GK_ATOM(svgStopFrame, "SVGStopFrame")
GK_ATOM(svgSwitchFrame, "SVGSwitchFrame")
GK_ATOM(svgTextFrame, "SVGTextFrame")
GK_ATOM(svgTextFrame2, "SVGTextFrame2")
GK_ATOM(svgTextPathFrame, "SVGTextPathFrame")
GK_ATOM(svgTSpanFrame, "SVGTSpanFrame")
GK_ATOM(svgUseFrame, "SVGUseFrame")

View File

@ -381,6 +381,8 @@ MOCHITEST_FILES_B = \
test_bug562652.html \
test_bug562137.html \
file_bug562137.txt \
test_bug562169-1.html \
test_bug562169-2.html \
test_bug548193.html \
file_bug548193.sjs \
test_html_colors_quirks.html \

View File

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=562169
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 562169</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
<p id="display"></p>
<div id="content" style="display: none">
<div dir="rtl" id="z"></div>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 562169 **/
/** Test that adding an child to an element with dir="rtl" makes the
child have rtl directionality, and removing the child makes it
go back to ltr directionality **/
function checkSelector(element, expectedDir, expectedChild)
{
ok(element.querySelector(":dir("+expectedDir+")") == expectedChild,
"direction should be " + expectedDir);
}
var x = document.createElement("div");
var y = document.createElement("div");
x.appendChild(y);
checkSelector(x, "ltr", y);
$(z).appendChild(x);
checkSelector(x, "rtl", y);
$(z).removeChild(x);
checkSelector(x, "ltr", y);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=562169
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 562169</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 562169 **/
/** Test that a newly created element has ltr directionality **/
ok(document.createElement("div").mozMatchesSelector(":dir(ltr)"),
"Element should be ltr on creation");
</script>
</pre>
</body>
</html>

View File

@ -248,6 +248,10 @@ private:
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
// Platform does not support plugin content (some mobile platforms)
#define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
// Element is ltr (for :dir pseudo-class)
#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
// Element is rtl (for :dir pseudo-class)
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
/**
* NOTE: do not go over 63 without updating nsEventStates::InternalType!

View File

@ -53,6 +53,7 @@
#include "nsHTMLParts.h"
#include "nsContentUtils.h"
#include "mozilla/dom/DirectionalityUtils.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsGkAtoms.h"
@ -96,6 +97,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::directionality;
class nsINodeInfo;
class nsIDOMNodeList;
@ -1687,6 +1689,24 @@ nsGenericHTMLElement::UpdateEditableState(bool aNotify)
nsStyledElement::UpdateEditableState(aNotify);
}
nsEventStates
nsGenericHTMLElement::IntrinsicState() const
{
nsEventStates state = nsGenericHTMLElementBase::IntrinsicState();
if (GetDirectionality() == eDir_RTL) {
state |= NS_EVENT_STATE_RTL;
state &= ~NS_EVENT_STATE_LTR;
} else { // at least for HTML, directionality is exclusively LTR or RTL
NS_ASSERTION(GetDirectionality() == eDir_LTR,
"HTML element's directionality must be either RTL or LTR");
state |= NS_EVENT_STATE_LTR;
state &= ~NS_EVENT_STATE_RTL;
}
return state;
}
nsresult
nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
@ -1889,6 +1909,20 @@ nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
else if (aNotify && aName == nsGkAtoms::spellcheck) {
SyncEditorsOnSubtree(this);
}
else if (aName == nsGkAtoms::dir) {
Directionality dir;
if (aValue &&
(aValue->Equals(nsGkAtoms::ltr, eIgnoreCase) ||
aValue->Equals(nsGkAtoms::rtl, eIgnoreCase))) {
SetHasValidDir();
dir = aValue->Equals(nsGkAtoms::rtl, eIgnoreCase) ? eDir_RTL : eDir_LTR;
SetDirectionality(this, dir, aNotify);
} else {
ClearHasValidDir();
dir = RecomputeDirectionality(this, aNotify);
}
SetDirectionalityOnDescendants(this, dir, aNotify);
}
}
return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,

View File

@ -49,6 +49,8 @@ public:
{
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
"Unexpected namespace");
AddStatesSilently(NS_EVENT_STATE_LTR);
SetFlags(NODE_HAS_DIRECTION_LTR);
}
/** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
@ -202,6 +204,8 @@ public:
virtual void UpdateEditableState(bool aNotify);
virtual nsEventStates IntrinsicState() const;
// Helper for setting our editable flag and notifying
void DoSetEditableFlag(bool aEditable, bool aNotify) {
SetEditableFlag(aEditable);

View File

@ -116,8 +116,7 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate)
}
mAudioStream = nsAudioStream::AllocateStream();
nsresult rv = mAudioStream->Init(aChannels, aRate,
nsAudioStream::FORMAT_FLOAT32);
nsresult rv = mAudioStream->Init(aChannels, aRate);
if (NS_FAILED(rv)) {
mAudioStream->Shutdown();
mAudioStream = nullptr;

View File

@ -2821,6 +2821,8 @@ void nsHTMLMediaElement::PlaybackEnded()
return;
}
Pause();
FireTimeUpdate(false);
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
}

View File

@ -1103,8 +1103,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStream(GraphTime aAudioOutputStartTime
aStream->mAudioPlaybackStartTime = aAudioOutputStartTime;
aStream->mAudioOutput = nsAudioStream::AllocateStream();
aStream->mAudioOutput->Init(audio->GetChannels(),
track->GetRate(),
audio->GetFirstFrameFormat());
track->GetRate());
}
void

View File

@ -60,7 +60,7 @@ class nsNativeAudioStream : public nsAudioStream
~nsNativeAudioStream();
nsNativeAudioStream();
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
void Shutdown();
nsresult Write(const void* aBuf, PRUint32 aFrames);
PRUint32 Available();
@ -95,7 +95,7 @@ class nsRemotedAudioStream : public nsAudioStream
nsRemotedAudioStream();
~nsRemotedAudioStream();
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
void Shutdown();
nsresult Write(const void* aBuf, PRUint32 aFrames);
PRUint32 Available();
@ -422,11 +422,11 @@ nsNativeAudioStream::~nsNativeAudioStream()
NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream)
nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate)
{
mRate = aRate;
mChannels = aNumChannels;
mFormat = aFormat;
mFormat = MOZ_AUDIO_DATA_FORMAT;
if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
NULL,
@ -474,53 +474,28 @@ nsresult nsNativeAudioStream::Write(const void* aBuf, PRUint32 aFrames)
if (s_data) {
double scaled_volume = GetVolumeScale() * mVolume;
switch (mFormat) {
case FORMAT_U8: {
const PRUint8* buf = static_cast<const PRUint8*>(aBuf);
PRInt32 volume = PRInt32((1 << 16) * scaled_volume);
for (PRUint32 i = 0; i < samples; ++i) {
s_data[i] = short(((PRInt32(buf[i]) - 128) * volume) >> 8);
}
break;
}
case FORMAT_S16_LE: {
const short* buf = static_cast<const short*>(aBuf);
PRInt32 volume = PRInt32((1 << 16) * scaled_volume);
for (PRUint32 i = 0; i < samples; ++i) {
short s = buf[i];
#if defined(IS_BIG_ENDIAN)
s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8);
#endif
s_data[i] = short((PRInt32(s) * volume) >> 16);
}
break;
}
case FORMAT_FLOAT32: {
const float* buf = static_cast<const float*>(aBuf);
for (PRUint32 i = 0; i < samples; ++i) {
float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume);
if (buf[i] < 0.0) {
s_data[i] = (scaled_value < -32768.0) ?
-32768 :
short(scaled_value);
} else {
s_data[i] = (scaled_value > 32767.0) ?
32767 :
short(scaled_value);
}
}
break;
const SampleType* buf = static_cast<const SampleType*>(aBuf);
for (PRUint32 i = 0; i < samples; ++i) {
float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume);
if (buf[i] < 0.0) {
s_data[i] = (scaled_value < -32768.0) ?
-32768 :
short(scaled_value);
} else {
s_data[i] = (scaled_value > 32767.0) ?
32767 :
short(scaled_value);
}
}
}
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
s_data.get(),
samples * sizeof(short)) != SA_SUCCESS)
{
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
mInError = true;
return NS_ERROR_FAILURE;
}
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
s_data.get(),
samples * sizeof(short)) != SA_SUCCESS)
{
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
mInError = true;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
@ -644,26 +619,12 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsRemotedAudioStream)
nsresult
nsRemotedAudioStream::Init(PRInt32 aNumChannels,
PRInt32 aRate,
SampleFormat aFormat)
PRInt32 aRate)
{
mRate = aRate;
mChannels = aNumChannels;
mFormat = aFormat;
switch (mFormat) {
case FORMAT_U8: {
mBytesPerFrame = sizeof(PRUint8) * mChannels;
break;
}
case FORMAT_S16_LE: {
mBytesPerFrame = sizeof(short) * mChannels;
break;
}
case FORMAT_FLOAT32: {
mBytesPerFrame = sizeof(float) * mChannels;
}
}
mFormat = MOZ_AUDIO_DATA_FORMAT;
mBytesPerFrame = sizeof(SampleType) * mChannels;
nsCOMPtr<nsIRunnable> event = new AudioInitEvent(this);
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
@ -861,7 +822,7 @@ class nsBufferedAudioStream : public nsAudioStream
nsBufferedAudioStream();
~nsBufferedAudioStream();
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
void Shutdown();
nsresult Write(const void* aBuf, PRUint32 aFrames);
PRUint32 Available();
@ -963,7 +924,7 @@ nsBufferedAudioStream::~nsBufferedAudioStream()
NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream)
nsresult
nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate)
{
cubeb* cubebContext = GetCubebContext();
@ -973,23 +934,13 @@ nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aF
mRate = aRate;
mChannels = aNumChannels;
mFormat = aFormat;
mFormat = MOZ_AUDIO_DATA_FORMAT;
cubeb_stream_params params;
params.rate = aRate;
params.channels = aNumChannels;
switch (aFormat) {
case FORMAT_S16_LE:
params.format = CUBEB_SAMPLE_S16LE;
mBytesPerFrame = sizeof(short) * aNumChannels;
break;
case FORMAT_FLOAT32:
params.format = CUBEB_SAMPLE_FLOAT32NE;
mBytesPerFrame = sizeof(float) * aNumChannels;
break;
default:
return NS_ERROR_FAILURE;
}
params.format = CUBEB_SAMPLE_FLOAT32NE;
mBytesPerFrame = sizeof(float) * aNumChannels;
{
cubeb_stream* stream;
@ -1221,29 +1172,10 @@ nsBufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
output += input_size[i];
} else {
// Adjust volume as each sample is copied out.
switch (mFormat) {
case FORMAT_S16_LE: {
PRInt32 volume = PRInt32(1 << 16) * scaled_volume;
const short* src = static_cast<const short*>(input[i]);
short* dst = reinterpret_cast<short*>(output);
for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
dst[j] = short((PRInt32(src[j]) * volume) >> 16);
}
output += input_size[i];
break;
}
case FORMAT_FLOAT32: {
const float* src = static_cast<const float*>(input[i]);
float* dst = reinterpret_cast<float*>(output);
for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
dst[j] = src[j] * scaled_volume;
}
output += input_size[i];
break;
}
default:
return -1;
const float* src = static_cast<const float*>(input[i]);
float* dst = reinterpret_cast<float*>(output);
for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
dst[j] = src[j] * scaled_volume;
}
}
}

View File

@ -11,6 +11,14 @@
#include "nsIThread.h"
#include "nsAutoPtr.h"
#ifndef MOZ_FLOATING_POINT_AUDIO
#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE)
typedef short SampleType;
#else
#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32)
typedef float SampleType;
#endif
// Access to a single instance of this class must be synchronized by
// callers, or made from a single thread. One exception is that access to
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels,Format}
@ -28,8 +36,7 @@ public:
nsAudioStream()
: mRate(0),
mChannels(0),
mFormat(FORMAT_S16_LE)
mChannels(0)
{}
virtual ~nsAudioStream();
@ -56,7 +63,7 @@ public:
// (22050Hz, 44100Hz, etc).
// Unsafe to call with a monitor held due to synchronous event execution
// on the main thread, which may attempt to acquire any held monitor.
virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) = 0;
virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate) = 0;
// Closes the stream. All future use of the stream is an error.
// Unsafe to call with a monitor held due to synchronous event execution
@ -106,7 +113,7 @@ public:
int GetRate() { return mRate; }
int GetChannels() { return mChannels; }
SampleFormat GetFormat() { return mFormat; }
SampleFormat GetFormat() { return MOZ_AUDIO_DATA_FORMAT; }
protected:
nsCOMPtr<nsIThread> mAudioPlaybackThread;

View File

@ -957,7 +957,7 @@ nsresult nsBuiltinDecoder::GetSeekable(nsTimeRanges* aSeekable)
return NS_OK;
}
if (mDecoderStateMachine->IsSeekableInBufferedRanges()) {
if (mDecoderStateMachine && mDecoderStateMachine->IsSeekableInBufferedRanges()) {
return GetBuffered(aSeekable);
} else {
// The stream is not seekable using only buffered ranges, and is not

View File

@ -52,12 +52,11 @@ public:
bool mHasVideo;
};
#ifdef MOZ_TREMOR
#ifndef MOZ_FLOATING_POINT_AUDIO
#include <ogg/os_types.h>
typedef ogg_int32_t VorbisPCMValue;
typedef short AudioDataValue;
#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE)
#define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767)
// Convert the output of vorbis_synthesis_pcmout to a AudioDataValue
#define MOZ_CONVERT_VORBIS_SAMPLE(x) \
@ -66,12 +65,11 @@ typedef short AudioDataValue;
#define MOZ_CONVERT_AUDIO_SAMPLE(x) ((x)*(1.F/32768))
#define MOZ_SAMPLE_TYPE_S16LE 1
#else /*MOZ_VORBIS*/
#else /* MOZ_FLOATING_POINT_AUDIO == 1*/
typedef float VorbisPCMValue;
typedef float AudioDataValue;
#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32)
#define MOZ_CONVERT_VORBIS_SAMPLE(x) (x)
#define MOZ_CONVERT_AUDIO_SAMPLE(x) (x)
#define MOZ_SAMPLE_TYPE_FLOAT32 1

View File

@ -1008,7 +1008,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
// are unsafe to call with the decoder monitor held are documented as such
// in nsAudioStream.h.
nsRefPtr<nsAudioStream> audioStream = nsAudioStream::AllocateStream();
audioStream->Init(channels, rate, MOZ_AUDIO_DATA_FORMAT);
audioStream->Init(channels, rate);
{
// We must hold the monitor while setting mAudioStream or whenever we query

View File

@ -14,10 +14,16 @@ var manager = new MediaTestManager;
function ended(evt) {
var v = evt.target;
is(v.paused, false, v._name + " must not be paused after end");
is(v.gotPause, true, "We should have received a \"pause\" event.")
is(v.paused, true, v._name + " must be paused after end");
manager.finished(v.token);
}
function pause(evt) {
var v = evt.target;
v.gotPause = true;
}
function startTest(test, token) {
var v = document.createElement('video');
v.token = token;
@ -31,6 +37,7 @@ function startTest(test, token) {
v.play();
is(v.paused, false, v._name + " must not be paused after play");
v.addEventListener("pause", pause, false);
v.addEventListener("ended", ended, false);
}

View File

@ -32,6 +32,7 @@ function seekStarted(evt) {
function seekEnded(evt) {
var v = evt.target;
v._gotSeekEnded = true;
v.play();
}
function loadedData(evt) {

View File

@ -2497,14 +2497,12 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
// Ok, compile it to create a prototype script object!
nsScriptObjectHolder<JSScript> newScriptObject(context);
uint32_t opts = JS_GetOptions(context->GetNativeContext());
if (!mOutOfLine) {
// If the script was inline, tell the JS parser to save source for
// Function.prototype.toSource(). If it's outline, we retrieve the
// source from the files on demand.
opts &= ~JSOPTION_ONLY_CNG_SOURCE;
JS_SetOptions(context->GetNativeContext(), opts);
}
// If the script was inline, tell the JS parser to save source for
// Function.prototype.toSource(). If it's out of line, we retrieve the
// source from the files on demand.
bool saveSource = !mOutOfLine;
rv = context->CompileScript(aText,
aTextLength,
// Use the enclosing document's principal
@ -2517,8 +2515,8 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
urlspec.get(),
aLineNo,
mLangVersion,
newScriptObject);
JS_SetOptions(context->GetNativeContext(), opts);
newScriptObject,
saveSource);
if (NS_FAILED(rv))
return rv;

View File

@ -97,14 +97,4 @@ LoadContext::GetAppId(PRUint32* aAppId)
return NS_OK;
}
NS_IMETHODIMP
LoadContext::GetExtendedOrigin(nsIURI* aUri, nsACString& aResult)
{
MOZ_ASSERT(mIsNotNull);
nsIScriptSecurityManager* ssmgr = nsContentUtils::GetSecurityManager();
return ssmgr->GetExtendedOrigin(aUri, mAppId, mIsInBrowserElement, aResult);
}
} // namespace mozilla

View File

@ -11395,20 +11395,6 @@ nsDocShell::GetIsContent(bool *aIsContent)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetExtendedOrigin(nsIURI *aUri, nsACString &aResult)
{
bool isInBrowserElement;
GetIsInBrowserElement(&isInBrowserElement);
nsCOMPtr<nsIScriptSecurityManager> ssmgr =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
NS_ENSURE_TRUE(ssmgr, NS_ERROR_FAILURE);
return ssmgr->GetExtendedOrigin(aUri, mAppId, isInBrowserElement, aResult);
}
bool
nsDocShell::IsOKToLoadURI(nsIURI* aURI)
{

View File

@ -228,7 +228,6 @@ public:
NS_IMETHOD GetIsContent(bool*);
NS_IMETHOD GetUsePrivateBrowsing(bool*);
NS_IMETHOD SetUsePrivateBrowsing(bool);
NS_IMETHOD GetExtendedOrigin(nsIURI *uri, nsACString & retval);
// Restores a cached presentation from history (mLSHE).
// This method swaps out the content viewer and simulates loads for

View File

@ -7,14 +7,13 @@
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsIURI;
/**
* An nsILoadContext represents the context of a load. This interface
* can be queried for various information about where the load is
* happening.
*/
[scriptable, uuid(386806c3-c4cb-4b3d-b05d-c08ea10f5585)]
[scriptable, uuid(48b5bf16-e0c7-11e1-b28e-91726188709b)]
interface nsILoadContext : nsISupports
{
/**
@ -79,19 +78,4 @@ interface nsILoadContext : nsISupports
*/
readonly attribute unsigned long appId;
/**
* Get the extended origin of a channel in this load context.
* The extended origin is a string that has more information than the origin
* and can be used to isolate data or permissions between different
* principals while taking into account parameters like the app id or the
* fact that the load is taking place in a mozbrowser.
*
* In some cases this function will simply return the origin for the
* channel's URI.
*
* The extendedOrigin is intended to be an opaque identifier. It is
* currently "human-readable" but no callers should assume it will stay
* as-is and it might be crypto-hashed at some point.
*/
AUTF8String GetExtendedOrigin(in nsIURI channel);
};

View File

@ -274,7 +274,7 @@ let DOMApplicationRegistry = {
let clone = {
installOrigin: aApp.installOrigin,
origin: aApp.origin,
receipts: aApp.receipts,
receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
installTime: aApp.installTime,
manifestURL: aApp.manifestURL,
progress: aApp.progress || 0.0,

View File

@ -45,8 +45,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
#define NS_ISCRIPTCONTEXT_IID \
{ 0x9a4df96d, 0xa231, 0x4108, \
{ 0xb5, 0xbc, 0xaf, 0x67, 0x7a, 0x36, 0xa7, 0x44 } }
{ 0x8bdcea47, 0x6704, 0x4dd9, \
{ 0xa1, 0x48, 0x05, 0x34, 0xcf, 0xe2, 0xdd, 0x57 } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -114,6 +114,7 @@ public:
* @param aVersion the script language version to use when executing
* @param aScriptObject an executable object that's the result of compiling
* the script.
* @param aSaveSource force the source code to be saved by the JS engine in memory
*
* @return NS_OK if the script source was valid and got compiled.
*
@ -124,7 +125,8 @@ public:
const char* aURL,
PRUint32 aLineNo,
PRUint32 aVersion,
nsScriptObjectHolder<JSScript>& aScriptObject) = 0;
nsScriptObjectHolder<JSScript>& aScriptObject,
bool aSaveSource = false) = 0;
/**
* Execute a precompiled script object.

View File

@ -1082,21 +1082,6 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime)
mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | JSOPTION_ALLOW_XML;
// The JS engine needs to keep the source code around in order to implement
// Function.prototype.toSource(). JSOPTION_ONLY_CNG_SOURCE causes the JS
// engine to retain the source code for scripts compiled in compileAndGo mode
// and compiled function bodies (from JS_CompileFunction*). In practice, this
// means content scripts and event handlers. It'd be nice to stop there and
// simply stub out requests for source on chrome code. Life is not so easy,
// unfortunately. Nobody relies on chrome toSource() working in core browser
// code, but chrome tests use it. The worst offenders are addons, which like
// to monkeypatch chrome functions by calling toSource() on them and using
// regular expression to modify them. So, even though we don't keep it in
// memory, we have to provide a way to get chrome source somehow. Enter
// SourceHook. When the JS engine is asked to provide the source for a
// function it doesn't have in memory, it calls this function to load it.
mDefaultJSOptions |= JSOPTION_ONLY_CNG_SOURCE;
mContext = ::JS_NewContext(aRuntime, gStackSize);
if (mContext) {
::JS_SetContextPrivate(mContext, static_cast<nsIScriptContext *>(this));
@ -1563,7 +1548,8 @@ nsJSContext::CompileScript(const PRUnichar* aText,
const char *aURL,
PRUint32 aLineNo,
PRUint32 aVersion,
nsScriptObjectHolder<JSScript>& aScriptObject)
nsScriptObjectHolder<JSScript>& aScriptObject,
bool aSaveSource /* = false */)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
@ -1590,15 +1576,20 @@ nsJSContext::CompileScript(const PRUnichar* aText,
XPCAutoRequest ar(mContext);
JSScript* script =
::JS_CompileUCScriptForPrincipalsVersion(mContext,
scopeObject,
nsJSPrincipals::get(aPrincipal),
static_cast<const jschar*>(aText),
aTextLength,
aURL,
aLineNo,
JSVersion(aVersion));
JS::CompileOptions options(mContext);
JS::CompileOptions::SourcePolicy sp = aSaveSource ?
JS::CompileOptions::SAVE_SOURCE :
JS::CompileOptions::LAZY_SOURCE;
options.setPrincipals(nsJSPrincipals::get(aPrincipal))
.setFileAndLine(aURL, aLineNo)
.setVersion(JSVersion(aVersion))
.setSourcePolicy(sp);
JS::RootedObject rootedScope(mContext, scopeObject);
JSScript* script = JS::Compile(mContext,
rootedScope,
options,
static_cast<const jschar*>(aText),
aTextLength);
if (!script) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2027,9 +2018,8 @@ nsJSContext::Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject)
if (!aScriptObject)
return NS_ERROR_FAILURE;
return nsContentUtils::XPConnect()->WriteScript(aStream, mContext, aScriptObject);
xpc_UnmarkGrayScript(aScriptObject);
return nsContentUtils::XPConnect()->WriteScript(aStream, mContext,
xpc_UnmarkGrayScript(aScriptObject));
}
nsresult
@ -2630,14 +2620,14 @@ TraceMallocDumpAllocations(JSContext *cx, unsigned argc, jsval *vp)
}
static JSFunctionSpec TraceMallocFunctions[] = {
{"TraceMallocDisable", TraceMallocDisable, 0, 0},
{"TraceMallocEnable", TraceMallocEnable, 0, 0},
{"TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0},
{"TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0},
{"TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0},
{"TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0},
{"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0},
{nullptr, nullptr, 0, 0}
JS_FS("TraceMallocDisable", TraceMallocDisable, 0, 0),
JS_FS("TraceMallocEnable", TraceMallocEnable, 0, 0),
JS_FS("TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0),
JS_FS("TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0),
JS_FS("TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0),
JS_FS("TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0),
JS_FS("TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0),
JS_FS_END
};
#endif /* NS_TRACE_MALLOC */
@ -3952,8 +3942,7 @@ ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, PRUint
/*
The JS engine calls this function when it needs the source for a chrome JS
function. See the comment in nsJSContext::nsJSContext about
JSOPTION_ONLY_CGN_SOURCE.
function. See the comment in nsJSRuntime::Init().
*/
static bool
SourceHook(JSContext *cx, JSScript *script, jschar **src, uint32_t *length)
@ -3977,7 +3966,6 @@ SourceHook(JSContext *cx, JSScript *script, jschar **src, uint32_t *length)
return true;
}
//static
nsresult
nsJSRuntime::Init()
@ -4000,6 +3988,22 @@ nsJSRuntime::Init()
rv = sRuntimeService->GetRuntime(&sRuntime);
NS_ENSURE_SUCCESS(rv, rv);
// The JS engine needs to keep the source code around in order to implement
// Function.prototype.toSource(). It'd be nice to not have to do this for
// chrome code and simply stub out requests for source on it. Life is not so
// easy, unfortunately. Nobody relies on chrome toSource() working in core
// browser code, but chrome tests use it. The worst offenders are addons,
// which like to monkeypatch chrome functions by calling toSource() on them
// and using regular expressions to modify them. We avoid keeping most browser
// JS source code in memory by setting LAZY_SOURCE on JS::CompileOptions when
// compiling some chrome code. This causes the JS engine not save the source
// code in memory. When the JS engine is asked to provide the source for a
// function compiled with LAZY_SOURCE, it calls SourceHook to load it.
///
// Note we do have to retain the source code in memory for scripts compiled in
// compileAndGo mode and compiled function bodies (from
// JS_CompileFunction*). In practice, this means content scripts and event
// handlers.
JS_SetSourceHook(sRuntime, SourceHook);
// Let's make sure that our main thread is the same as the xpcom main thread.
@ -4015,6 +4019,11 @@ nsJSRuntime::Init()
};
JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
static js::DOMCallbacks DOMcallbacks = {
InstanceClassHasProtoAtDepth
};
SetDOMCallbacks(sRuntime, &DOMcallbacks);
// Set these global xpconnect options...
Preferences::RegisterCallback(MaxScriptRunTimePrefChangedCallback,
"dom.max_script_run_time");

View File

@ -72,7 +72,8 @@ public:
const char *aURL,
PRUint32 aLineNo,
PRUint32 aVersion,
nsScriptObjectHolder<JSScript>& aScriptObject);
nsScriptObjectHolder<JSScript>& aScriptObject,
bool aSaveSource = false);
virtual nsresult ExecuteScript(JSScript* aScriptObject,
JSObject* aScopeObject,
nsAString* aRetValue,

View File

@ -40,11 +40,7 @@ def main():
o = OptionParser(usage=usagestring)
o.add_option("--verbose-errors", action='store_true', default=False,
help="When an error happens, display the Python traceback.")
o.add_option("--use-jsop-accessors", action='store_true', default=False,
dest='useJSOPAccessors',
help="Use JSPropertyOps instead of JSNatives for getters and setters")
(options, args) = o.parse_args()
Codegen.generateNativeAccessors = not options.useJSOPAccessors
if len(args) != 4 or (args[0] != "header" and args[0] != "cpp"):
o.error(usagestring)

View File

@ -242,7 +242,8 @@ JSObject*
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
JSObject* protoProto, JSClass* protoClass,
JSClass* constructorClass, JSNative constructor,
unsigned ctorNargs, Prefable<JSFunctionSpec>* methods,
unsigned ctorNargs, JSClass* instanceClass,
Prefable<JSFunctionSpec>* methods,
Prefable<JSPropertySpec>* properties,
Prefable<ConstantSpec>* constants,
Prefable<JSFunctionSpec>* staticMethods, const char* name)
@ -264,6 +265,9 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
if (!proto) {
return NULL;
}
js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
JS::PrivateValue(instanceClass));
}
else {
proto = NULL;
@ -323,6 +327,19 @@ DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
}
// Can only be called with the immediate prototype of the instance object. Can
// only be called on the prototype of an object known to be a DOM instance.
JSBool
InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID,
uint32_t depth)
{
JSClass* instanceClass = static_cast<JSClass*>(
js::GetReservedSlot(protoObject, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate());
MOZ_ASSERT(IsDOMClass(instanceClass));
DOMJSClass* domClass = DOMJSClass::FromJSClass(instanceClass);
return (uint32_t)domClass->mInterfaceChain[depth] == protoID;
}
// Only set allowNativeWrapper to false if you really know you need it, if in
// doubt use true. Setting it to false disables security wrappers.
bool
@ -431,11 +448,12 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
size_t i = methods[prefIdx].specs - methodSpecs;
for ( ; methodIds[i] != JSID_VOID; ++i) {
if (id == methodIds[i]) {
JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call,
JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call.op,
methodSpecs[i].nargs, 0,
wrapper, id);
if (!fun)
return false;
SET_JITINFO(fun, methodSpecs[i].call.info);
JSObject *funobj = JS_GetFunctionObject(fun);
desc->value.setObject(*funobj);
desc->attrs = methodSpecs[i].flags;
@ -456,10 +474,34 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
size_t i = attributes[prefIdx].specs - attributeSpecs;
for ( ; attributeIds[i] != JSID_VOID; ++i) {
if (id == attributeIds[i]) {
desc->attrs = attributeSpecs[i].flags;
// Because of centralization, we need to make sure we fault in the
// JitInfos as well. At present, until the JSAPI changes, the easiest
// way to do this is wrap them up as functions ourselves.
desc->attrs = attributeSpecs[i].flags & ~JSPROP_NATIVE_ACCESSORS;
// They all have getters, so we can just make it.
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
JSFunction *fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].getter.op,
0, 0, global, NULL);
if (!fun)
return false;
SET_JITINFO(fun, attributeSpecs[i].getter.info);
JSObject *funobj = JS_GetFunctionObject(fun);
desc->getter = js::CastAsJSPropertyOp(funobj);
desc->attrs |= JSPROP_GETTER;
if (attributeSpecs[i].setter.op) {
// We have a setter! Make it.
fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].setter.op,
1, 0, global, NULL);
if (!fun)
return false;
SET_JITINFO(fun, attributeSpecs[i].setter.info);
funobj = JS_GetFunctionObject(fun);
desc->setter = js::CastAsJSStrictPropertyOp(funobj);
desc->attrs |= JSPROP_SETTER;
} else {
desc->setter = NULL;
}
desc->obj = wrapper;
desc->setter = attributeSpecs[i].setter;
desc->getter = attributeSpecs[i].getter;
return true;
}
}

View File

@ -287,6 +287,8 @@ struct Prefable {
* object of constructorClass, unless that's also null, in which
* case we should not create an interface object at all.
* ctorNargs is the length of the constructor function; 0 if no constructor
* instanceClass is the JSClass of instance objects for this class. This can
* be null if this is not a concrete proto.
* methods and properties are to be defined on the interface prototype object;
* these arguments are allowed to be null if there are no
* methods or properties respectively.
@ -307,7 +309,8 @@ JSObject*
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
JSObject* protoProto, JSClass* protoClass,
JSClass* constructorClass, JSNative constructor,
unsigned ctorNargs, Prefable<JSFunctionSpec>* methods,
unsigned ctorNargs, JSClass* instanceClass,
Prefable<JSFunctionSpec>* methods,
Prefable<JSPropertySpec>* properties,
Prefable<ConstantSpec>* constants,
Prefable<JSFunctionSpec>* staticMethods, const char* name);
@ -552,6 +555,12 @@ GetParentPointer(const ParentObject& aObject)
return ToSupports(aObject.mObject);
}
// Can only be called with the immediate prototype of the instance object. Can
// only be called on the prototype of an object known to be a DOM instance.
JSBool
InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID,
uint32_t depth);
// Only set allowNativeWrapper to false if you really know you need it, if in
// doubt use true. Setting it to false disables security wrappers.
bool

View File

@ -138,7 +138,8 @@ class CGPrototypeJSClass(CGThing):
def define(self):
return """
static JSClass PrototypeClass = {
"%sPrototype", 0,
"%sPrototype",
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
@ -932,11 +933,14 @@ class MethodDefiner(PropertyDefiner):
return m["pref"]
def specData(m):
return (m["name"], m["name"], m["length"], m["flags"])
isQI = (m["name"] == 'QueryInterface')
jitinfo = ("&%s_methodinfo" % m["name"]) if not isQI else "NULL"
accessor = "genericMethod" if not isQI else "QueryInterface"
return (m["name"], accessor, jitinfo, m["length"], m["flags"])
return self.generatePrefableArray(
array, name,
' JS_FN("%s", %s, %s, %s)',
' JS_FNINFO("%s", %s, %s, %s, %s)',
' JS_FS_END',
'JSFunctionSpec',
pref, specData, doIdArrays)
@ -953,20 +957,17 @@ class AttrDefiner(PropertyDefiner):
return ""
def flags(attr):
flags = "JSPROP_SHARED | JSPROP_ENUMERATE"
if generateNativeAccessors:
flags = "JSPROP_NATIVE_ACCESSORS | " + flags
elif attr.readonly:
return "JSPROP_READONLY | " + flags
return flags
return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS"
def getter(attr):
return "get_" + attr.identifier.name
return ("{(JSPropertyOp)genericGetter, &%(name)s_getterinfo}"
% {"name" : attr.identifier.name})
def setter(attr):
if attr.readonly:
return "NULL"
return "set_" + attr.identifier.name
return "JSOP_NULLWRAPPER"
return ("{(JSStrictPropertyOp)genericSetter, &%(name)s_setterinfo}"
% {"name" : attr.identifier.name})
def specData(attr):
return (attr.identifier.name, flags(attr), getter(attr),
@ -974,8 +975,8 @@ class AttrDefiner(PropertyDefiner):
return self.generatePrefableArray(
array, name,
' { "%s", 0, %s, (JSPropertyOp)%s, (JSStrictPropertyOp)%s }',
' { 0, 0, 0, 0, 0 }',
' { "%s", 0, %s, %s, %s}',
' { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }',
'JSPropertySpec',
PropertyDefiner.getControllingPref, specData, doIdArrays)
@ -1123,12 +1124,14 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
call = CGGeneric(("return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,\n"
" %s, %s, %s, %d,\n"
" %s,\n"
" %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n"
" %s);") % (
"&PrototypeClass" if needInterfacePrototypeObject else "NULL",
"&InterfaceObjectClass" if needInterfaceObjectClass else "NULL",
constructHook if needConstructor else "NULL",
constructArgs,
"&Class.mBase" if self.descriptor.concrete else "NULL",
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
if self.properties.hasChromeOnly():
@ -2402,6 +2405,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
"successCode" is the code to run once we have successfully done the
conversion. The resulting string should be used with string.Template, it
needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
Returns (templateString, infallibility of conversion template)
"""
haveSuccessCode = successCode is not None
if not haveSuccessCode:
@ -2440,7 +2445,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
return str
if type is None or type.isVoid():
return setValue("JSVAL_VOID")
return (setValue("JSVAL_VOID"), True)
if type.isArray():
raise TypeError("Can't handle array return values yet")
@ -2448,14 +2453,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
if type.isSequence():
if type.nullable():
# Nullable sequences are Nullable< nsTArray<T> >
return """
(recTemplate, recInfall) = getWrapTemplateForType(type.inner, descriptorProvider,
"%s.Value()" % result, successCode,
isCreator)
return ("""
if (%s.IsNull()) {
%s
}
%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(),
getWrapTemplateForType(type.inner, descriptorProvider,
"%s.Value()" % result, successCode,
isCreator))
%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), recTemplate), recInfall)
# Now do non-nullable sequences. We use setting the element
# in the array as our succcess code because when we succeed in
@ -2474,7 +2479,7 @@ if (%s.IsNull()) {
}
)
innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define()
return ("""
return (("""
uint32_t length = %s.Length();
JSObject *returnArray = JS_NewArrayObject(cx, length, NULL);
if (!returnArray) {
@ -2483,7 +2488,7 @@ if (!returnArray) {
jsval tmp;
for (uint32_t i = 0; i < length; ++i) {
%s
}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)")
}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)"), False)
if type.isGeckoInterface():
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
@ -2525,26 +2530,27 @@ for (uint32_t i = 0; i < length; ++i) {
getIID = ""
wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
wrappingCode += wrapAndSetPtr(wrap)
return wrappingCode
return (wrappingCode, False)
if type.isString():
if type.nullable():
return wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result)
return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False)
else:
return wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result)
return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False)
if type.isEnum():
if type.nullable():
raise TypeError("We don't support nullable enumerated return types "
"yet")
return """MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
return ("""MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
JSString* %(resultStr)s = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length);
if (!%(resultStr)s) {
return false;
}
""" % { "result" : result,
"resultStr" : result + "_str",
"strings" : type.inner.identifier.name + "Values::strings" } + setValue("JS::StringValue(%s_str)" % result)
"strings" : type.inner.identifier.name + "Values::strings" } +
setValue("JS::StringValue(%s_str)" % result), False)
if type.isCallback():
assert not type.isInterface()
@ -2552,12 +2558,14 @@ if (!%(resultStr)s) {
# nullable and always have [TreatNonCallableAsNull] for now.
# See comments in WrapNewBindingObject explaining why we need
# to wrap here.
return setValue("JS::ObjectOrNullValue(%s)" % result, True)
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
if type.tag() == IDLType.Tags.any:
# See comments in WrapNewBindingObject explaining why we need
# to wrap here.
return setValue(result, True)
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
return (setValue(result, True), False)
if type.isObject():
# See comments in WrapNewBindingObject explaining why we need
@ -2566,36 +2574,37 @@ if (!%(resultStr)s) {
toValue = "JS::ObjectOrNullValue(%s)"
else:
toValue = "JS::ObjectValue(*%s)"
return setValue(toValue % result, True)
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
return (setValue(toValue % result, True), False)
if not type.isPrimitive():
raise TypeError("Need to learn to wrap %s" % type)
if type.nullable():
(recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
"%s.Value()" % result, successCode,
isCreator)
return ("if (%s.IsNull()) {\n" % result +
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
"}\n" +
getWrapTemplateForType(type.inner, descriptorProvider,
"%s.Value()" % result, successCode,
isCreator))
"}\n" + recTemplate, recInfal)
tag = type.tag()
if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
IDLType.Tags.uint16, IDLType.Tags.int32]:
return setValue("INT_TO_JSVAL(int32_t(%s))" % result)
return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64, IDLType.Tags.float,
IDLType.Tags.double]:
# XXXbz will cast to double do the "even significand" thing that webidl
# calls for for 64-bit ints? Do we care?
return setValue("JS_NumberValue(double(%s))" % result)
return (setValue("JS_NumberValue(double(%s))" % result), True)
elif tag == IDLType.Tags.uint32:
return setValue("UINT_TO_JSVAL(%s)" % result)
return (setValue("UINT_TO_JSVAL(%s)" % result), True)
elif tag == IDLType.Tags.bool:
return setValue("BOOLEAN_TO_JSVAL(%s)" % result)
return (setValue("BOOLEAN_TO_JSVAL(%s)" % result), True)
else:
raise TypeError("Need to learn to wrap primitive: %s" % type)
@ -2624,11 +2633,25 @@ def wrapForType(type, descriptorProvider, templateValues):
wrap = getWrapTemplateForType(type, descriptorProvider,
templateValues.get('result', 'result'),
templateValues.get('successCode', None),
templateValues.get('isCreator', False))
templateValues.get('isCreator', False))[0]
defaultValues = {'obj': 'obj'}
return string.Template(wrap).substitute(defaultValues, **templateValues)
def infallibleForAttr(attr, descriptorProvider):
"""
Determine the fallibility of changing a C++ value of IDL type "type" into
JS for the given attribute. Apart from isCreator, all the defaults are used,
since the fallbility does not change based on the boolean values,
and the template will be discarded.
CURRENT ASSUMPTIONS:
We assume that successCode for wrapping up return values cannot contain
failure conditions.
"""
return getWrapTemplateForType(attr.type, descriptorProvider, 'result', None,\
memberIsCreator(attr))[1]
def typeNeedsCx(type):
return (type is not None and
(type.isCallback() or type.isAny() or type.isObject() or
@ -2823,7 +2846,7 @@ class CGPerSignatureCall(CGThing):
return not 'infallible' in self.extendedAttributes
def wrap_return_value(self):
isCreator = self.idlNode.getExtendedAttribute("Creator") is not None
isCreator = memberIsCreator(self.idlNode)
if isCreator:
# We better be returning addrefed things!
assert isResultAlreadyAddRefed(self.descriptor,
@ -3129,39 +3152,15 @@ class CGMethodCall(CGThing):
def define(self):
return self.cgRoot.define()
class CGGetterSetterCall(CGPerSignatureCall):
"""
A class to generate a native object getter or setter call for a
particular IDL getter or setter.
"""
def __init__(self, returnType, arguments, nativeMethodName, descriptor,
attr, getter=False, setter=False):
assert bool(getter) != bool(setter)
CGPerSignatureCall.__init__(self, returnType, [], arguments,
nativeMethodName, False, descriptor, attr,
getter=getter, setter=setter)
def getArgv(self):
if generateNativeAccessors:
return CGPerSignatureCall.getArgv(self)
return "vp"
class CGGetterCall(CGGetterSetterCall):
class CGGetterCall(CGPerSignatureCall):
"""
A class to generate a native object getter call for a particular IDL
getter.
"""
def __init__(self, returnType, nativeMethodName, descriptor, attr):
CGGetterSetterCall.__init__(self, returnType, [], nativeMethodName,
descriptor, attr, getter=True)
def getArgc(self):
if generateNativeAccessors:
return CGGetterSetterCall.getArgc()
return "0"
def getArgvDecl(self):
if generateNativeAccessors:
return CGPerSignatureCall.getArgvDecl(self)
# We just get our stuff from vp
return ""
CGPerSignatureCall.__init__(self, returnType, [], [],
nativeMethodName, False, descriptor,
attr, getter=True)
class FakeArgument():
def __init__(self, type):
@ -3170,33 +3169,22 @@ class FakeArgument():
self.variadic = False
self.defaultValue = None
class CGSetterCall(CGGetterSetterCall):
class CGSetterCall(CGPerSignatureCall):
"""
A class to generate a native object setter call for a particular IDL
setter.
"""
def __init__(self, argType, nativeMethodName, descriptor, attr):
CGGetterSetterCall.__init__(self, None, [FakeArgument(argType)],
nativeMethodName, descriptor, attr,
CGPerSignatureCall.__init__(self, None, [], [FakeArgument(argType)],
nativeMethodName, False, descriptor, attr,
setter=True)
def wrap_return_value(self):
if generateNativeAccessors:
return CGGetterSetterCall.wrap_return_value(self)
# We have no return value
return "\nreturn true;"
def getArgc(self):
if generateNativeAccessors:
return CGGetterSetterCall.getArgc(self)
return "1"
def getArgvDecl(self):
if generateNativeAccessors:
return (CGPerSignatureCall.getArgvDecl(self) +
"jsval undef = JS::UndefinedValue();\n"
"if (argc == 0) {\n"
" argv = &undef;\n"
" argc = 1;\n"
"}")
# We just get our stuff from vp
# We just get our stuff from our last arg no matter what
return ""
class FakeCastableDescriptor():
@ -3231,7 +3219,7 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
def getThis(self):
return CGIndenter(
CGGeneric("JSObject* obj = JS_THIS_OBJECT(cx, vp);\n"
CGGeneric("JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
"if (!obj) {\n"
" return false;\n"
"}\n"
@ -3244,77 +3232,168 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
def MakeNativeName(name):
return name[0].upper() + name[1:]
class CGNativeMethod(CGAbstractBindingMethod):
class CGGenericMethod(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL method..
"""
def __init__(self, descriptor, method):
self.method = method
baseName = method.identifier.name
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractBindingMethod.__init__(self, descriptor, baseName, args)
CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args)
def generate_code(self):
return CGIndenter(CGGeneric(
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"JSJitMethodOp method = (JSJitMethodOp)info->op;\n"
"return method(cx, obj, self, argc, vp);"))
class CGSpecializedMethod(CGAbstractStaticMethod):
"""
A class for generating the C++ code for a specialized method that the JIT
can call with lower overhead.
"""
def __init__(self, descriptor, method):
self.method = method
name = method.identifier.name
args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
Argument('%s*' % descriptor.nativeType, 'self'),
Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')]
CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
def definition_body(self):
name = self.method.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
return CGMethodCall([], nativeName, self.method.isStatic(),
self.descriptor, self.method)
self.descriptor, self.method).define()
class CGNativeGetter(CGAbstractBindingMethod):
class CGGenericGetter(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL attribute getter.
"""
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractBindingMethod.__init__(self, descriptor, 'genericGetter', args)
def generate_code(self):
return CGIndenter(CGGeneric(
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"JSJitPropertyOp getter = info->op;\n"
"return getter(cx, obj, self, vp);"))
class CGSpecializedGetter(CGAbstractStaticMethod):
"""
A class for generating the code for a specialized attribute getter
that the JIT can call with lower overhead.
"""
def __init__(self, descriptor, attr):
self.attr = attr
name = 'get_' + attr.identifier.name
if generateNativeAccessors:
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
else:
args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
Argument('JSHandleId', 'id'), Argument('JS::Value*', 'vp')]
CGAbstractBindingMethod.__init__(self, descriptor, name, args)
args = [ Argument('JSContext*', 'cx'),
Argument('JSHandleObject', 'obj'),
Argument('%s*' % descriptor.nativeType, 'self'),
Argument('JS::Value*', 'vp') ]
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
def getThis(self):
if generateNativeAccessors:
return CGAbstractBindingMethod.getThis(self)
return CGIndenter(
CGGeneric("%s* self;" % self.descriptor.nativeType))
def generate_code(self):
def definition_body(self):
name = self.attr.identifier.name
nativeName = "Get" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
return CGIndenter(CGGetterCall(self.attr.type, nativeName, self.descriptor,
self.attr))
return CGIndenter(CGGetterCall(self.attr.type, nativeName,
self.descriptor, self.attr)).define()
class CGNativeSetter(CGAbstractBindingMethod):
class CGGenericSetter(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL attribute setter.
"""
def __init__(self, descriptor, attr):
self.attr = attr
baseName = attr.identifier.name
name = 'set_' + attr.identifier.name
if generateNativeAccessors:
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
else:
args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
Argument('JSHandleId', 'id'), Argument('JSBool', 'strict'),
Argument('JS::Value*', 'vp')]
CGAbstractBindingMethod.__init__(self, descriptor, name, args)
def getThis(self):
if generateNativeAccessors:
return CGAbstractBindingMethod.getThis(self)
return CGIndenter(
CGGeneric("%s* self;" % self.descriptor.nativeType))
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
Argument('JS::Value*', 'vp')]
CGAbstractBindingMethod.__init__(self, descriptor, 'genericSetter', args)
def generate_code(self):
return CGIndenter(CGGeneric(
"JS::Value* argv = JS_ARGV(cx, vp);\n"
"JS::Value undef = JS::UndefinedValue();\n"
"if (argc == 0) {\n"
" argv = &undef;\n"
"}\n"
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"JSJitPropertyOp setter = info->op;\n"
"if (!setter(cx, obj, self, argv)) {\n"
" return false;\n"
"}\n"
"*vp = JSVAL_VOID;\n"
"return true;"))
class CGSpecializedSetter(CGAbstractStaticMethod):
"""
A class for generating the code for a specialized attribute setter
that the JIT can call with lower overhead.
"""
def __init__(self, descriptor, attr):
self.attr = attr
name = 'set_' + attr.identifier.name
args = [ Argument('JSContext*', 'cx'),
Argument('JSHandleObject', 'obj'),
Argument('%s*' % descriptor.nativeType, 'self'),
Argument('JS::Value*', 'argv')]
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
def definition_body(self):
name = self.attr.identifier.name
nativeName = "Set" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
return CGIndenter(CGSetterCall(self.attr.type, nativeName, self.descriptor,
self.attr))
return CGIndenter(CGSetterCall(self.attr.type, nativeName,
self.descriptor, self.attr)).define()
def memberIsCreator(member):
return member.getExtendedAttribute("Creator") is not None
class CGMemberJITInfo(CGThing):
"""
A class for generating the JITInfo for a property that points to
our specialized getter and setter.
"""
def __init__(self, descriptor, member):
self.member = member
self.descriptor = descriptor
def declare(self):
return ""
def defineJitInfo(self, infoName, opName, infallible):
protoID = "prototypes::id::%s" % self.descriptor.interface.identifier.name
depth = "PrototypeTraits<%s>::Depth" % protoID
failstr = "true" if infallible else "false"
return ("\n"
"const JSJitInfo %s = {\n"
" %s,\n"
" %s,\n"
" %s,\n"
" %s, /* isInfallible. Only relevant for getters. */\n"
" false /* isConstant. Only relevant for getters. */\n"
"};\n" % (infoName, opName, protoID, depth, failstr))
def define(self):
if self.member.isAttr():
getterinfo = ("%s_getterinfo" % self.member.identifier.name)
getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
getterinfal = getterinfal and infallibleForAttr(self.member, self.descriptor)
result = self.defineJitInfo(getterinfo, getter, getterinfal)
if not self.member.readonly:
setterinfo = ("%s_setterinfo" % self.member.identifier.name)
setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
# Setters are always fallible, since they have to do a typed unwrap.
result += self.defineJitInfo(setterinfo, setter, False)
return result
if self.member.isMethod():
methodinfo = ("%s_methodinfo" % self.member.identifier.name)
# Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
method = ("(JSJitPropertyOp)%s" % self.member.identifier.name)
# Method, much like setters, are always fallible
result = self.defineJitInfo(methodinfo, method, False)
return result
raise TypeError("Illegal member type to CGPropertyJITInfo")
def getEnumValueName(value):
# Some enum values can be empty strings. Others might have weird
@ -4052,14 +4131,23 @@ class CGDescriptor(CGThing):
cgThings = []
if descriptor.interface.hasInterfacePrototypeObject():
cgThings.extend([CGNativeMethod(descriptor, m) for m in
descriptor.interface.members if
m.isMethod() and not m.isStatic()])
cgThings.extend([CGNativeGetter(descriptor, a) for a in
descriptor.interface.members if a.isAttr()])
cgThings.extend([CGNativeSetter(descriptor, a) for a in
descriptor.interface.members if
a.isAttr() and not a.readonly])
hasMethod, hasGetter, hasSetter = False, False, False
for m in descriptor.interface.members:
if m.isMethod() and not m.isStatic():
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
elif m.isAttr():
cgThings.append(CGSpecializedGetter(descriptor, m))
hasGetter = True
if not m.readonly:
cgThings.append(CGSpecializedSetter(descriptor, m))
hasSetter = True
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
if hasSetter: cgThings.append(CGGenericSetter(descriptor))
if descriptor.concrete:
if not descriptor.workers and descriptor.wrapperCache:

View File

@ -23,6 +23,11 @@
// We use these flag bits for the new bindings.
#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
namespace mozilla {
namespace dom {

View File

@ -39,11 +39,7 @@ def main():
help="Directory in which to cache lex/parse tables.")
o.add_option("--verbose-errors", action='store_true', default=False,
help="When an error happens, display the Python traceback.")
o.add_option("--use-jsop-accessors", action='store_true', default=False,
dest='useJSOPAccessors',
help="Use JSPropertyOps instead of JSNatives for getters and setters")
(options, args) = o.parse_args()
Codegen.generateNativeAccessors = not options.useJSOPAccessors
if len(args) < 2:
o.error(usageString)

View File

@ -16,15 +16,6 @@ EXPORT_LIBRARY = 1
include $(topsrcdir)/config/config.mk
# Define USE_JSOP_ACCESSORS to a nonempty string like "yes" to use them
USE_JSOP_ACCESSORS =
ifdef USE_JSOP_ACCESSORS
DEFINES += -DUSE_JSOP_ACCESSORS
ACCESSOR_OPT = --use-jsop-accessors
else
ACCESSOR_OPT =
endif
# Need this to find all our DOM source files.
include $(topsrcdir)/dom/dom-config.mk
@ -106,7 +97,7 @@ $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
$(NULL)
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) -I$(srcdir)/parser \
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) header \
$(srcdir)/BindingGen.py header \
$(srcdir)/Bindings.conf $*Binding \
$*.webidl
@ -115,7 +106,7 @@ $(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \
$(NULL)
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) -I$(srcdir)/parser \
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp \
$(srcdir)/BindingGen.py cpp \
$(srcdir)/Bindings.conf $*Binding \
$*.webidl
@ -141,7 +132,7 @@ ParserResults.pkl: $(globalgen_dependencies) \
$(all_webidl_files)
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) -I$(srcdir)/parser \
$(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf . \
$(srcdir)/GlobalGen.py $(srcdir)/Bindings.conf . \
--cachedir=$(CACHE_DIR) \
$(all_webidl_files)

View File

@ -13,8 +13,8 @@
#include "BluetoothReplyRunnable.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
#include "nsIDOMDOMRequest.h"
#include "nsIPermissionManager.h"
#include "nsDOMClassInfo.h"
#include "nsDOMEvent.h"
#include "nsThreadUtils.h"
@ -22,10 +22,7 @@
#include "mozilla/LazyIdleThread.h"
#include "mozilla/Util.h"
#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist"
using namespace mozilla;
using mozilla::Preferences;
USING_BLUETOOTH_NAMESPACE
@ -276,11 +273,27 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
{
NS_ASSERTION(aWindow, "Null pointer!");
bool allowed;
nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed);
nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
aWindow :
aWindow->GetCurrentInnerWindow();
// Need the document for security check.
nsCOMPtr<nsIDocument> document = innerWindow->GetExtantDoc();
NS_ENSURE_TRUE(document, NS_NOINTERFACE);
nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED);
PRUint32 permission;
nsresult rv =
permMgr->TestPermissionFromPrincipal(principal, "mozBluetooth", &permission);
NS_ENSURE_SUCCESS(rv, rv);
if (!allowed) {
if (permission != nsIPermissionManager::ALLOW_ACTION) {
*aBluetoothManager = nullptr;
return NS_OK;
}
@ -290,6 +303,7 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
NS_ERROR("Cannot create bluetooth manager!");
return NS_ERROR_FAILURE;
}
bluetoothManager.forget(aBluetoothManager);
return NS_OK;
}

View File

@ -187,6 +187,11 @@ public:
const nsAString& aDeviceAddress,
nsAString& aDevicePath) = 0;
virtual int
GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
const nsAString& aPattern,
int aAttributeId) = 0;
protected:
BluetoothService()
{

View File

@ -338,7 +338,9 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
// This happens when the array is 0-length. Apparently we get a
// DBUS_TYPE_INVALID type.
propertyValue = InfallibleTArray<nsString>();
#ifdef DEBUG
NS_WARNING("Received array type that's not a string array!");
#endif
}
break;
default:
@ -605,7 +607,7 @@ BluetoothDBusService::StartInternal()
}
if (mConnection) {
return NS_OK;
return NS_OK;
}
if (NS_FAILED(EstablishDBusConnection())) {
@ -613,7 +615,23 @@ BluetoothDBusService::StartInternal()
StopDBus();
return NS_ERROR_FAILURE;
}
DBusError err;
dbus_error_init(&err);
// Set which messages will be processed by this dbus connection.
// Since we are maintaining a single thread for all the DBus bluez
// signals we want, register all of them in this thread at startup.
// The event handler will sort the destinations out as needed.
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_add_match(mConnection,
sBluetoothDBusSignals[i],
&err);
if (dbus_error_is_set(&err)) {
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
// Add a filter for all incoming messages_base
if (!dbus_connection_add_filter(mConnection, EventFilter,
NULL, NULL)) {
@ -634,7 +652,20 @@ BluetoothDBusService::StopInternal()
StopDBus();
return NS_OK;
}
dbus_connection_remove_filter(mConnection, EventFilter, NULL);
DBusError err;
dbus_error_init(&err);
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_remove_match(mConnection,
sBluetoothDBusSignals[i],
&err);
if (dbus_error_is_set(&err)) {
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
dbus_connection_remove_filter(mConnection, EventFilter, nullptr);
mConnection = nullptr;
mBluetoothSignalObserverTable.Clear();
StopDBus();
@ -837,3 +868,24 @@ BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress);
return true;
}
int
BluetoothDBusService::GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
const nsAString& aPattern,
int aAttributeId)
{
// This is a blocking call, should not be run on main thread.
MOZ_ASSERT(!NS_IsMainThread());
const char* deviceObjectPath = NS_ConvertUTF16toUTF8(aObjectPath).get();
const char* pattern = NS_ConvertUTF16toUTF8(aPattern).get();
DBusMessage *reply =
dbus_func_args(mConnection, deviceObjectPath,
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
DBUS_TYPE_STRING, &pattern,
DBUS_TYPE_UINT16, &aAttributeId,
DBUS_TYPE_INVALID);
return reply ? dbus_returns_int32(reply) : -1;
}

View File

@ -44,6 +44,10 @@ public:
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath);
virtual int
GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
const nsAString& aPattern,
int aAttributeId);
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,

View File

@ -117,12 +117,26 @@ const ContentPanning = {
let nodeContent = node.ownerDocument.defaultView;
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
if (node.scrollHeight > node.clientHeight ||
node.scrollWidth > node.clientWidth ||
('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
('scrollTopMax' in node && node.scrollTopMax > 0)) {
let style = nodeContent.getComputedStyle(node, null);
let overflow = [style.getPropertyValue('overflow'),
style.getPropertyValue('overflow-x'),
style.getPropertyValue('overflow-y')];
let rect = node.getBoundingClientRect();
let isAuto = (overflow.indexOf('auto') != -1 &&
(rect.height < node.scrollHeight ||
rect.width < node.scrollWidth));
let isScroll = (overflow.indexOf('scroll') != -1);
let isScrollableTextarea = (node.tagName == 'TEXTAREA' &&
(node.scrollHeight > node.clientHeight ||
node.scrollWidth > node.clientWidth ||
('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
('scrollTopMax' in node && node.scrollTopMax > 0)));
if (isScroll || isAuto || isScrollableTextarea)
return [node, this._generateCallback(node)];
}
node = node.parentNode;
}
@ -133,7 +147,11 @@ const ContentPanning = {
// root scrollable frame, so don't use our synchronous fallback.
return [null, null];
return [nodeContent, this._generateCallback(nodeContent)];
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
return [nodeContent, this._generateCallback(nodeContent)];
}
return [null, null];
},
_generateCallback: function cp_generateCallback(content) {

View File

@ -7,7 +7,7 @@
#include "nsDOMClassInfo.h"
#include "DictionaryHelpers.h"
#define DOM_CAMERA_LOG_LEVEL 3
#define DOM_CAMERA_LOG_LEVEL DOM_CAMERA_LOG_NOTHING
#include "CameraCommon.h"
using namespace mozilla;

View File

@ -168,6 +168,21 @@ Contact.prototype = {
}
};
function _checkBlobArray(aBlob) {
if (Array.isArray(aBlob)) {
for (let i = 0; i < aBlob.length; i++) {
if (typeof aBlob != 'object') {
return null;
}
if (!(aBlob[i] instanceof Components.interfaces.nsIDOMBlob)) {
return null;
}
}
return aBlob;
}
return null;
};
this.name = _create(aProp.name) || null;
this.honorificPrefix = _create(aProp.honorificPrefix) || null;
this.givenName = _create(aProp.givenName) || null;
@ -185,7 +200,7 @@ Contact.prototype = {
this.email = null;
}
this.photo = _create(aProp.photo) || null;
this.photo = _checkBlobArray(aProp.photo) || null;
this.url = _create(aProp.url) || null;
this.category = _create(aProp.category) || null;

View File

@ -17,6 +17,7 @@ DIRS = \
MOCHITEST_FILES = \
test_contacts_basics.html \
test_contacts_events.html \
test_contacts_blobs.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -99,7 +99,6 @@ var properties2 = {
jobTitle: ["boss", "superboss"],
bday: new Date("1980, 12, 01"),
note: "test note",
photo: ["pic1", "pic2"],
category: ["cat1", "cat2"],
url: ["www.1.com", "www.2.com"],
anniversary: new Date("2000, 12, 01"),
@ -165,7 +164,6 @@ function checkContacts(contact1, contact2) {
checkStr(contact1.familyName, contact2.familyName, "Same familyName");
checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
checkStr(contact1.nickname, contact2.nickname, "Same nickname");
checkStr(contact1.photo, contact2.photo, "Same photo");
checkStr(contact1.url, contact2.url, "Same url");
checkStr(contact1.category, contact2.category, "Same category");
checkStr(contact1.org, contact2.org, "Same org");

View File

@ -0,0 +1,324 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
-->
<head>
<title>Test for Bug {674720} WebContacts</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={674720}">Mozilla Bug {674720}</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
"use strict";
var comp = SpecialPowers.wrap(Components);
comp.utils.import("resource://gre/modules/ContactService.jsm");
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
SpecialPowers.addPermission("contacts", true, document);
var utils = SpecialPowers.getDOMWindowUtils(window);
function getView(size)
{
var buffer = new ArrayBuffer(size);
var view = new Uint8Array(buffer);
is(buffer.byteLength, size, "Correct byte length");
return view;
}
function getRandomView(size)
{
var view = getView(size);
for (var i = 0; i < size; i++) {
view[i] = parseInt(Math.random() * 255)
}
return view;
}
function getBlob(type, view)
{
return utils.getBlob([view], {type: type});
}
function getRandomBlob(size)
{
return getBlob("binary/random", getRandomView(size));
}
function compareBuffers(buffer1, buffer2)
{
if (buffer1.byteLength != buffer2.byteLength) {
return false;
}
var view1 = new Uint8Array(buffer1);
var view2 = new Uint8Array(buffer2);
for (var i = 0; i < buffer1.byteLength; i++) {
if (view1[i] != view2[i]) {
return false;
}
}
return true;
}
function verifyBuffers(buffer1, buffer2, isLast)
{
ok(compareBuffers(buffer1, buffer2), "Correct blob data");
if (isLast)
next();
}
var randomBlob = getRandomBlob(1024);
var randomBlob2 = getRandomBlob(1024);
var properties1 = {
name: "xTestname1",
photo: [randomBlob]
};
var properties2 = {
name: "yTestname2",
photo: [randomBlob, randomBlob2]
};
var sample_id1;
var createResult1;
var findResult1;
function onUnwantedSuccess() {
ok(false, "onUnwantedSuccess: shouldn't get here");
}
function onFailure() {
ok(false, "in on Failure!");
}
function verifyBlob(blob1, blob2, isLast)
{
dump("islast? " + isLast + "\n");
is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
"Instance of nsIDOMBlob");
is(blob1 instanceof Components.interfaces.nsIDOMFile,
blob2 instanceof Components.interfaces.nsIDOMFile,
"Instance of nsIDOMFile");
is(blob1.size, blob2.size, "Correct size");
is(blob1.type, blob2.type, "Correct type");
var buffer1;
var buffer2;
var reader1 = new FileReader();
reader1.readAsArrayBuffer(blob2);
reader1.onload = function(event) {
buffer2 = event.target.result;
if (buffer1) {
verifyBuffers(buffer1, buffer2, isLast);
}
}
var reader2 = new FileReader();
reader2.readAsArrayBuffer(blob1);
reader2.onload = function(event) {
buffer1 = event.target.result;
if (buffer2) {
verifyBuffers(buffer1, buffer2, isLast);
}
}
}
function verifyBlobArray(blobs1, blobs2)
{
is(blobs1 instanceof Array, true, "Got an array object");
is(blobs1.length, blobs2.length, "Correct length");
if (!blobs1.length) {
next();
return;
}
for (var i = 0; i < blobs1.length; i++)
verifyBlob(blobs1[i], blobs2[i], i == blobs1.length - 1);
}
var req;
var index = 0;
var mozContacts = window.navigator.mozContacts
var steps = [
function () {
ok(true, "Deleting database");
req = mozContacts.clear();
req.onsuccess = function () {
ok(true, "Deleted the database");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding contact with photo");
createResult1 = new mozContact();
createResult1.init(properties1);
dump("CreateResult1: " + JSON.stringify(createResult1));
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
ok(findResult1.id == sample_id1, "Same ID");
verifyBlobArray(createResult1.photo, properties1.photo);
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding contact with 2 photos");
createResult1 = new mozContact();
createResult1.init(properties2);
dump("CreateResult1: " + JSON.stringify(createResult1));
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties2.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
ok(findResult1.id == sample_id1, "Same ID");
verifyBlobArray(createResult1.photo, properties2.photo);
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding photo as String");
createResult1 = new mozContact();
createResult1.init({name: "asdf", photo: ["xyz"]});
dump("CreateResult1: " + JSON.stringify(createResult1));
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
is(createResult1.photo, null, "No photo")
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding photo as String");
createResult1 = new mozContact();
createResult1.init({name: "jkl", photo: "xyz"});
dump("CreateResult1: " + JSON.stringify(createResult1));
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
is(createResult1.photo, null, "No photo")
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: "asdf"};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
ok(findResult1.id == sample_id1, "Same ID");
is(findResult1.photo, null, "No photo");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding photo as Object");
createResult1 = new mozContact();
createResult1.init({photo: [{}]});
dump("CreateResult1: " + JSON.stringify(createResult1));
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
is(createResult1.photo, null, "No photo")
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
req = mozContacts.clear()
req.onsuccess = function () {
ok(true, "Deleted the database");
next();
}
req.onerror = onFailure;
},
function () {
ok(true, "all done!\n");
SimpleTest.finish();
}
];
function next() {
ok(true, "Begin!");
if (index >= steps.length) {
ok(false, "Shouldn't get here!");
return;
}
try {
steps[index]();
} catch(ex) {
ok(false, "Caught exception", ex);
}
index += 1;
}
function permissionTest() {
if (gContactsEnabled) {
next();
} else {
is(mozContacts, null, "mozContacts is null when not enabled.");
SimpleTest.finish();
}
}
var gContactsEnabled = SpecialPowers.getBoolPref("dom.mozContacts.enabled");
SimpleTest.waitForExplicitFinish();
addLoadEvent(permissionTest);
ok(true, "test passed");
</script>
</pre>
</body>
</html>

View File

@ -41,7 +41,8 @@ EnumerateToTArray(const PRUint64& aKey,
nsresult
FileManager::Init(nsIFile* aDirectory,
mozIStorageConnection* aConnection)
mozIStorageConnection* aConnection,
FactoryPrivilege aPrivilege)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
@ -103,8 +104,10 @@ FileManager::Init(nsIFile* aDirectory,
NS_ENSURE_SUCCESS(rv, rv);
if (flag) {
rv = ss->UpdateQuotaInformationForFile(file);
NS_ENSURE_SUCCESS(rv, rv);
if (aPrivilege != Chrome) {
rv = ss->UpdateQuotaInformationForFile(file);
NS_ENSURE_SUCCESS(rv, rv);
}
}
else {
rv = file->Remove(false);

View File

@ -60,7 +60,8 @@ public:
}
nsresult Init(nsIFile* aDirectory,
mozIStorageConnection* aConnection);
mozIStorageConnection* aConnection,
FactoryPrivilege aPrivilege);
nsresult Load(mozIStorageConnection* aConnection);

View File

@ -733,7 +733,7 @@ IndexedDatabaseManager::GetIndexedDBQuotaMB()
nsresult
IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
FactoryPrivilege mPrivilege,
FactoryPrivilege aPrivilege,
nsIFile** aDirectory)
{
#ifdef DEBUG
@ -786,7 +786,7 @@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
if (mPrivilege != Chrome) {
if (aPrivilege != Chrome) {
rv = ss->SetQuotaForFilenamePattern(pattern,
GetIndexedDBQuotaMB() * 1024 * 1024,
mQuotaCallbackSingleton, nsnull);
@ -878,12 +878,12 @@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
nsRefPtr<FileManager> fileManager = new FileManager(aOrigin, databaseName);
rv = fileManager->Init(fileManagerDirectory, connection);
rv = fileManager->Init(fileManagerDirectory, connection, aPrivilege);
NS_ENSURE_SUCCESS(rv, rv);
fileManagers->AppendElement(fileManager);
if (mPrivilege != Chrome) {
if (aPrivilege != Chrome) {
rv = ss->UpdateQuotaInformationForFile(file);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -1691,7 +1691,7 @@ OpenDatabaseHelper::DoDatabaseWork()
NS_ENSURE_TRUE(mFileManager, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!mFileManager->Inited()) {
rv = mFileManager->Init(fileManagerDirectory, connection);
rv = mFileManager->Init(fileManagerDirectory, connection, mPrivilege);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}

View File

@ -54,7 +54,7 @@ interface nsIDOMContactProperties : nsISupports
attribute jsval honorificSuffix; // DOMString[]
attribute jsval nickname; // DOMString[]
attribute jsval email; // ContactEmail[]
attribute jsval photo; // DOMString[]
attribute jsval photo; // nsIDOMBlob[]
attribute jsval url; // DOMString[]
attribute jsval category; // DOMString[]
attribute jsval adr; // ContactAddress[]

View File

@ -297,9 +297,7 @@ AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat)
{
mStream = nsAudioStream::AllocateStream();
NS_ASSERTION(mStream, "AudioStream allocation failed.");
if (NS_FAILED(mStream->Init(aNumChannels,
aRate,
(nsAudioStream::SampleFormat) aFormat))) {
if (NS_FAILED(mStream->Init(aNumChannels, aRate))) {
NS_WARNING("AudioStream initialization failed.");
mStream = nullptr;
return;

View File

@ -489,13 +489,9 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL)
bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
if (useOffMainThreadCompositing) {
// FIXME. Oh please fixme. Somehow.
//
// We need the child process's ProcessHandle to do
// PCompositor::Open() below (on win32 ... sigh). We don't
// get that until onconnect, but that's too late to open the
// compositor channel below.
mSubprocess->SyncLaunch();
// We need the subprocess's ProcessHandle to create the
// PCompositor channel below. Block just until we have that.
mSubprocess->LaunchAndWaitForProcessHandle();
} else {
mSubprocess->AsyncLaunch();
}

View File

@ -114,6 +114,7 @@ PEMQExpectedFeatureValue=Found invalid value for media feature.
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
PEAnonBoxNotAlone=Did not expect anonymous box.
PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
PESupportsConditionStartEOF='not' or '('
PESupportsConditionInParensStartEOF='not', '(' or identifier
PESupportsConditionNotEOF='not'

View File

@ -222,11 +222,19 @@ interface nsIDOMMozMobileConnection : nsIDOMEventTarget
attribute nsIDOMEventListener onussdreceived;
};
[scriptable, uuid(46321d6e-bbce-4b7b-aa32-d17b6aa984fe)]
[scriptable, uuid(6601c20e-337f-4286-8d6e-0990fc1c2372)]
interface nsIDOMMozMobileConnectionInfo : nsISupports
{
/**
* Indicates whether the device is connected to a mobile network.
* State of the connection.
*
* Possible values: 'notSearching', 'searching', 'denied', 'registered'.
* null if the state is unknown.
*/
readonly attribute DOMString state;
/**
* Indicates whether the connection is ready. This may be different
*/
readonly attribute bool connected;

View File

@ -3,3 +3,8 @@
b2g = true
browser = false
qemu = true
[test_mobile_voice_state.js]
b2g = true
browser = false
qemu = true

View File

@ -1,6 +1,5 @@
/* 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/. */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// getNetworks() can take some time..
MARIONETTE_TIMEOUT = 60000;
@ -35,15 +34,17 @@ function isTelkilaNetwork(network) {
function testConnectionInfo() {
let voice = connection.voice;
is(voice.connected, true);
is(voice.state, "registered");
is(voice.emergencyCallsOnly, false);
is(voice.roaming, false);
isAndroidNetwork(voice.network);
let data = connection.data;
// TODO Bug 762959: enable these checks when data state updates are implemented
// is(data.connected, true);
// is(data.emergencyCallsOnly, false);
// is(data.roaming, false);
// data.connected = true means there's an active data call which we
// can't predict here.
is(data.state, "registered");
is(data.emergencyCallsOnly, false);
is(data.roaming, false);
isAndroidNetwork(data.network);
testGetNetworks();

View File

@ -0,0 +1,115 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 30000;
const WHITELIST_PREF = "dom.mobileconnection.whitelist";
let uriPrePath = window.location.protocol + "//" + window.location.host;
SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
let connection = navigator.mozMobileConnection;
ok(connection instanceof MozMobileConnection,
"connection is instanceof " + connection.constructor);
function setEmulatorVoiceState(state) {
runEmulatorCmd("gsm voice " + state, function (result) {
is(result[0], "OK");
});
}
function testConnectionInfo() {
let voice = connection.voice;
is(voice.connected, true);
is(voice.state, "registered");
is(voice.emergencyCallsOnly, false);
is(voice.roaming, false);
testUnregistered();
}
function testUnregistered() {
setEmulatorVoiceState("unregistered");
connection.addEventListener("voicechange", function onvoicechange() {
connection.removeEventListener("voicechange", onvoicechange);
is(connection.voice.connected, false);
is(connection.voice.state, "notSearching");
is(connection.voice.emergencyCallsOnly, false);
is(connection.voice.roaming, false);
testSearching();
});
}
function testSearching() {
// For some reason, requesting the "searching" state puts the fake modem
// into "registered"... Skipping this test for now.
testDenied();
return;
setEmulatorVoiceState("searching");
connection.addEventListener("voicechange", function onvoicechange() {
connection.removeEventListener("voicechange", onvoicechange);
is(connection.voice.connected, false);
is(connection.voice.state, "searching");
is(connection.voice.emergencyCallsOnly, false);
is(connection.voice.roaming, false);
testDenied();
});
}
function testDenied() {
setEmulatorVoiceState("denied");
connection.addEventListener("voicechange", function onvoicechange() {
connection.removeEventListener("voicechange", onvoicechange);
is(connection.voice.connected, false);
is(connection.voice.state, "denied");
is(connection.voice.emergencyCallsOnly, false);
is(connection.voice.roaming, false);
testRoaming();
});
}
function testRoaming() {
setEmulatorVoiceState("roaming");
connection.addEventListener("voicechange", function onvoicechange() {
connection.removeEventListener("voicechange", onvoicechange);
is(connection.voice.connected, true);
is(connection.voice.state, "registered");
is(connection.voice.emergencyCallsOnly, false);
is(connection.voice.roaming, true);
testHome();
});
}
function testHome() {
setEmulatorVoiceState("home");
connection.addEventListener("voicechange", function onvoicechange() {
connection.removeEventListener("voicechange", onvoicechange);
is(connection.voice.connected, true);
is(connection.voice.state, "registered");
is(connection.voice.emergencyCallsOnly, false);
is(connection.voice.roaming, false);
cleanUp();
});
}
function cleanUp() {
SpecialPowers.clearUserPref(WHITELIST_PREF);
finish();
}
testConnectionInfo();

View File

@ -144,7 +144,7 @@ SettingsLock.prototype = {
throw Components.results.NS_ERROR_ABORT;
}
if (this._settingsManager.hasReadPrivileges || this._settingsManager.hasReadWritePrivileges) {
if (this._settingsManager.hasPrivileges) {
let req = Services.DOMRequest.createRequest(this._settingsManager._window);
this._requests.enqueue({ request: req, intent:"get", name: aName });
this.createTransactionAndProcess();
@ -161,7 +161,7 @@ SettingsLock.prototype = {
throw Components.results.NS_ERROR_ABORT;
}
if (this._settingsManager.hasReadWritePrivileges) {
if (this._settingsManager.hasPrivileges) {
let req = Services.DOMRequest.createRequest(this._settingsManager._window);
debug("send: " + JSON.stringify(aSettings));
this._requests.enqueue({request: req, intent: "set", settings: aSettings});
@ -179,7 +179,7 @@ SettingsLock.prototype = {
throw Components.results.NS_ERROR_ABORT;
}
if (this._settingsManager.hasReadWritePrivileges) {
if (this._settingsManager.hasPrivileges) {
let req = Services.DOMRequest.createRequest(this._settingsManager._window);
this._requests.enqueue({ request: req, intent: "clear"});
this.createTransactionAndProcess();
@ -227,7 +227,7 @@ SettingsManager.prototype = {
},
set onsettingchange(aCallback) {
if (this.hasReadPrivileges || this.hasReadWritePrivileges)
if (this.hasPrivileges)
this._onsettingchange = aCallback;
else
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -317,17 +317,9 @@ SettingsManager.prototype = {
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
let readPerm = principal == secMan.getSystemPrincipal()
? Ci.nsIPermissionManager.ALLOW_ACTION
: Services.perms.testExactPermissionFromPrincipal(principal, "websettings-read");
let readwritePerm = principal == secMan.getSystemPrincipal()
? Ci.nsIPermissionManager.ALLOW_ACTION
: Services.perms.testExactPermissionFromPrincipal(principal, "websettings-readwrite");
this.hasReadPrivileges = readPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
this.hasReadWritePrivileges = readwritePerm == Ci.nsIPermissionManager.ALLOW_ACTION;
debug("has read privileges :" + this.hasReadPrivileges + ", has read-write privileges: " + this.hasReadWritePrivileges);
let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "settings");
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
debug("has privileges :" + this.hasPrivileges);
},
observe: function(aSubject, aTopic, aData) {

View File

@ -24,8 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={678695}
var comp = SpecialPowers.wrap(Components);
comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
SpecialPowers.addPermission("websettings-read", true, document);
SpecialPowers.addPermission("websettings-readwrite", true, document);
SpecialPowers.addPermission("settings", true, document);
function onUnwantedSuccess() {
ok(false, "onUnwantedSuccess: shouldn't get here");

View File

@ -85,6 +85,7 @@ MobileConnectionInfo.prototype = {
// nsIDOMMozMobileConnectionInfo
connected: false,
state: null,
emergencyCallsOnly: false,
roaming: false,
network: null,

View File

@ -446,36 +446,32 @@ RadioInterfaceLayer.prototype = {
let selectionMessage = message[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE];
// Batch the *InfoChanged messages together
let voiceInfoChanged = false;
if (voiceMessage) {
voiceMessage.batch = true;
voiceInfoChanged = this.updateVoiceConnection(voiceMessage);
this.updateVoiceConnection(voiceMessage);
}
let dataInfoChanged = false;
if (dataMessage) {
dataMessage.batch = true;
dataInfoChanged = this.updateDataConnection(dataMessage);
this.updateDataConnection(dataMessage);
}
let voice = this.rilContext.voice;
let data = this.rilContext.data;
if (operatorMessage) {
if (this.networkChanged(operatorMessage, voice.network)) {
voiceInfoChanged = true;
voice.network = operatorMessage;
}
if (this.networkChanged(operatorMessage, data.network)) {
dataInfoChanged = true;
data.network = operatorMessage;
}
}
if (voiceInfoChanged) {
if (voiceMessage || operatorMessage) {
ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice);
}
if (dataInfoChanged) {
if (dataMessage || operatorMessage) {
ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
}
@ -488,96 +484,88 @@ RadioInterfaceLayer.prototype = {
* Sends the RIL:VoiceInfoChanged message when the voice
* connection's state has changed.
*
* @param state The new voice connection state. When state.batch is true,
* the RIL:VoiceInfoChanged message will not be sent.
* @return Whether or not this.radioState.voice was updated
* @param newInfo The new voice connection information. When newInfo.batch is true,
* the RIL:VoiceInfoChanged message will not be sent.
*/
updateVoiceConnection: function updateVoiceConnection(state) {
updateVoiceConnection: function updateVoiceConnection(newInfo) {
let voiceInfo = this.rilContext.voice;
let regState = state.regState;
voiceInfo.type = "gsm"; //TODO see bug 726098.
if (!state || regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
voiceInfo.connected = false;
voiceInfo.emergencyCallsOnly = false;
voiceInfo.roaming = false;
voiceInfo.state = newInfo.state;
voiceInfo.connected = newInfo.connected;
voiceInfo.roaming = newInfo.roaming;
voiceInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
// Unlike the data registration info, the voice info typically contains
// no (useful) radio tech information, so we have to manually set
// this here. (TODO GSM only for now, see bug 726098.)
voiceInfo.type = "gsm";
// Make sure we also reset the operator and signal strength information
// if we drop off the network.
if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
voiceInfo.network = null;
voiceInfo.type = null;
voiceInfo.signalStrength = null;
voiceInfo.relSignalStrength = null;
}
if (!newInfo.batch) {
ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
return false;
}
let isRoaming = regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING;
let isHome = regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME;
let isConnected = isRoaming || isHome;
let radioTech = RIL.GECKO_RADIO_TECH[state.radioTech] || null;
// Ensure that we check for changes before sending the message
if (voiceInfo.emergencyCallsOnly != state.emergencyCallsOnly ||
voiceInfo.connected != isConnected ||
voiceInfo.roaming != isRoaming ||
voiceInfo.type != radioTech) {
voiceInfo.emergencyCallsOnly = state.emergencyCallsOnly;
voiceInfo.connected = isConnected;
voiceInfo.roaming = isRoaming;
voiceInfo.type = radioTech;
// When batch is true, hold off on firing VoiceInfoChanged events
if (!state.batch) {
ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
}
return true;
}
return false;
},
updateDataConnection: function updateDataConnection(state) {
let data = this.rilContext.data;
if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
data.connected = false;
data.emergencyCallsOnly = false;
data.roaming = false;
data.network = null;
data.type = null;
data.signalStrength = null;
data.relSignalStrength = null;
ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
return false;
updateDataConnection: function updateDataConnection(newInfo) {
let dataInfo = this.rilContext.data;
dataInfo.state = newInfo.state;
dataInfo.roaming = newInfo.roaming;
dataInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
dataInfo.type = newInfo.type;
// For the data connection, the `connected` flag indicates whether
// there's an active data call.
dataInfo.connected = RILNetworkInterface.connected;
// Make sure we also reset the operator and signal strength information
// if we drop off the network.
if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
dataInfo.network = null;
dataInfo.signalStrength = null;
dataInfo.relSignalStrength = null;
}
if (!newInfo.batch) {
ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
}
data.roaming =
(state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING);
data.type = RIL.GECKO_RADIO_TECH[state.radioTech] || null;
ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
if (!this.dataCallSettings["enabled"]) {
return false;
return;
}
let isRegistered =
state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME ||
(this.dataCallSettings["roaming_enabled"] &&
state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING);
newInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED &&
(!newInfo.roaming || this._isDataRoamingEnabled());
let haveDataConnection =
state.radioTech != RIL.NETWORK_CREG_TECH_UNKNOWN;
newInfo.type != GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
if (isRegistered && haveDataConnection) {
debug("Radio is ready for data connection.");
this.updateRILNetworkInterface();
}
return false;
},
handleSignalStrengthChange: function handleSignalStrengthChange(message) {
let voiceInfo = this.rilContext.voice;
// TODO CDMA, EVDO, LTE, etc. (see bug 726098)
this.rilContext.voice.signalStrength = message.gsmDBM;
this.rilContext.voice.relSignalStrength = message.gsmRelative;
ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", this.rilContext.voice);
if (voiceInfo.signalStrength != message.gsmDBM ||
voiceInfo.relSignalStrength != message.gsmRelative) {
voiceInfo.signalStrength = message.gsmDBM;
voiceInfo.relSignalStrength = message.gsmRelative;
ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
}
this.rilContext.data.signalStrength = message.gsmDBM;
this.rilContext.data.relSignalStrength = message.gsmRelative;
ppmm.sendAsyncMessage("RIL:DataInfoChanged", this.rilContext.data);
let dataInfo = this.rilContext.data;
if (dataInfo.signalStrength != message.gsmDBM ||
dataInfo.relSignalStrength != message.gsmRelative) {
dataInfo.signalStrength = message.gsmDBM;
dataInfo.relSignalStrength = message.gsmRelative;
ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
}
},
networkChanged: function networkChanged(srcNetwork, destNetwork) {

View File

@ -1449,6 +1449,25 @@ const GECKO_NETWORK_SELECTION_UNKNOWN = null;
const GECKO_NETWORK_SELECTION_AUTOMATIC = "automatic";
const GECKO_NETWORK_SELECTION_MANUAL = "manual";
const GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null;
const GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching";
const GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching";
const GECKO_MOBILE_CONNECTION_STATE_REGISTERED = "registered";
const GECKO_MOBILE_CONNECTION_STATE_DENIED = "denied";
const NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE = {};
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_HOME] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_ROAMING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
const GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError";
const GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError";
const GECKO_CALL_ERROR_BUSY = "BusyError";

View File

@ -62,6 +62,9 @@ let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
// Marker object.
let PENDING_NETWORK_TYPE = {};
/**
* This object contains helpers buffering incoming data & deconstructing it
* into parcels as well as buffering outgoing data & constructing parcels.
@ -615,6 +618,8 @@ let RIL = {
*/
aid: null,
networkSelectionMode: null,
voiceRegistrationState: {},
dataRegistrationState: {},
@ -1504,10 +1509,7 @@ let RIL = {
*/
requestNetworkInfo: function requestNetworkInfo() {
if (this._processingNetworkInfo) {
if (DEBUG) {
debug("Already requesting network info: " +
JSON.stringify(this._pendingNetworkInfo));
}
if (DEBUG) debug("Network info requested, but we're already requesting network info.");
return;
}
@ -2172,19 +2174,21 @@ let RIL = {
return;
}
if (DEBUG) debug("Queuing " + type + " network info message: " + JSON.stringify(message));
this._pendingNetworkInfo[type] = message;
},
_receivedNetworkInfo: function _receivedNetworkInfo(type) {
if (DEBUG) debug("Received " + type + " network info.");
if (!this._processingNetworkInfo) {
return;
}
let pending = this._pendingNetworkInfo;
// We still need to track states for events that aren't fired
// We still need to track states for events that aren't fired.
if (!(type in pending)) {
pending[type] = true;
pending[type] = PENDING_NETWORK_TYPE;
}
// Pending network info is ready to be sent when no more messages
@ -2192,58 +2196,77 @@ let RIL = {
for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
let type = NETWORK_INFO_MESSAGE_TYPES[i];
if (!(type in pending)) {
if (DEBUG) debug("Still missing some more network info, not notifying main thread.");
return;
}
}
// Do a pass to clean up the processed messages that didn't create
// a response message, so we don't have unused keys in the outbound
// networkinfochanged message
let keys = Object.keys(pending);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
if (pending[key] === true) {
// networkinfochanged message.
for (let key in pending) {
if (pending[key] == PENDING_NETWORK_TYPE) {
delete pending[key];
}
}
if (DEBUG) debug("All pending network info has been received: " + JSON.stringify(pending));
// Send the message on the next tick of the worker's loop, so we give the
// last message a chance to call _sendNetworkInfoMessage first.
setTimeout(this._sendPendingNetworkInfo.bind(this), 0);
setTimeout(this._sendPendingNetworkInfo, 0);
},
_sendPendingNetworkInfo: function _sendPendingNetworkInfo() {
this.sendDOMMessage(this._pendingNetworkInfo);
RIL.sendDOMMessage(RIL._pendingNetworkInfo);
this._processingNetworkInfo = false;
RIL._processingNetworkInfo = false;
for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
delete RIL._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
}
},
/**
* Process the network registration flags.
*
* @return true if the state changed, false otherwise.
*/
_processCREG: function _processCREG(curState, newState) {
let changed = false;
let regState = RIL.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
if (curState.regState != regState) {
changed = true;
curState.regState = regState;
curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState];
curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
curState.emergencyCallsOnly =
(regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) &&
(regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS);
if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) {
curState.emergencyCallsOnly = !curState.connected;
}
}
let radioTech = RIL.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN);
if (curState.radioTech != radioTech) {
changed = true;
curState.radioTech = radioTech;
curState.type = GECKO_RADIO_TECH[radioTech] || null;
}
return changed;
},
_processVoiceRegistrationState: function _processVoiceRegistrationState(state) {
this.initRILQuirks();
let rs = this.voiceRegistrationState;
let stateChanged = false;
let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
if (rs.regState != regState) {
rs.regState = regState;
if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) {
rs.emergencyCallsOnly =
(regState != NETWORK_CREG_STATE_REGISTERED_HOME) &&
(regState != NETWORK_CREG_STATE_REGISTERED_ROAMING);
} else {
rs.emergencyCallsOnly =
(regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) &&
(regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS);
}
stateChanged = true;
if (regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
regState == NETWORK_CREG_STATE_REGISTERED_ROAMING) {
RIL.getSMSCAddress();
}
let stateChanged = this._processCREG(rs, state);
if (stateChanged && rs.connected) {
RIL.getSMSCAddress();
}
let cell = this.cellLocation;
@ -2268,12 +2291,6 @@ let RIL = {
this.sendDOMMessage(cell);
}
let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
if (rs.radioTech != radioTech) {
rs.radioTech = radioTech;
stateChanged = true;
}
// TODO: This zombie code branch that will be raised from the dead once
// we add explicit CDMA support everywhere (bug 726098).
let cdma = false;
@ -2301,20 +2318,7 @@ let RIL = {
_processDataRegistrationState: function _processDataRegistrationState(state) {
let rs = this.dataRegistrationState;
let stateChanged = false;
let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
if (rs.regState != regState) {
rs.regState = regState;
stateChanged = true;
}
let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
if (rs.radioTech != radioTech) {
rs.radioTech = radioTech;
stateChanged = true;
}
let stateChanged = this._processCREG(rs, state);
if (stateChanged) {
rs.rilMessageType = "dataregistrationstatechange";
this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs);
@ -2333,7 +2337,7 @@ let RIL = {
}
let [longName, shortName, networkTuple] = operatorData;
let thisTuple = String(this.operator.mcc) + this.operator.mnc;
let thisTuple = "" + this.operator.mcc + this.operator.mnc;
if (this.operator.longName !== longName ||
this.operator.shortName !== shortName ||
@ -3180,11 +3184,8 @@ RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
}
let operatorData = Buf.readStringList();
if (DEBUG) debug("operator: " + operatorData);
if (DEBUG) debug("Operator: " + operatorData);
this._processOperator(operatorData);
};
RIL[REQUEST_RADIO_POWER] = null;
RIL[REQUEST_DTMF] = null;
@ -3383,8 +3384,8 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELEC
break;
}
if (this.mode != selectionMode) {
this.mode = options.mode = selectionMode;
if (this.networkSelectionMode != selectionMode) {
this.networkSelectionMode = options.mode = selectionMode;
options.rilMessageType = "networkselectionmodechange";
this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
}

View File

@ -39,8 +39,7 @@ force_prompt(true);
var comp = SpecialPowers.wrap(Components);
SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
SpecialPowers.addPermission("websettings-read", true, document);
SpecialPowers.addPermission("websettings-readwrite", true, document);
SpecialPowers.addPermission("settings", true, document);
comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
toggleGeolocationSetting(false, function() {

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