mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 12:35:58 +00:00
Merge from mozilla-central.
This commit is contained in:
commit
8d084d5b2e
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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'
|
||||
];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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];
|
||||
|
@ -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];
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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) "$@"
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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 =
|
||||
|
@ -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 \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -39,6 +39,8 @@ endif #} INCLUDED_XPIDL_MK
|
||||
###########################################################################
|
||||
ifdef _xpidl-todo_ #{
|
||||
|
||||
$(call requiredfunction,install_cmd)
|
||||
|
||||
## Logic batch #1
|
||||
xpidl-install-src-preqs=\
|
||||
$(XPIDLSRCS) \
|
||||
|
@ -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
|
||||
|
@ -595,6 +595,7 @@ psap.h
|
||||
Pt.h
|
||||
pthread.h
|
||||
pthread_np.h
|
||||
pulse/pulseaudio.h
|
||||
pwd.h
|
||||
Python.h
|
||||
QDOffscreen.h
|
||||
|
@ -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) $@
|
||||
|
@ -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():
|
||||
|
66
configure.in
66
configure.in
@ -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 =
|
||||
|
58
content/base/public/DirectionalityUtils.h
Normal file
58
content/base/public/DirectionalityUtils.h
Normal 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___ */
|
@ -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
|
||||
|
@ -48,6 +48,7 @@ $(NULL)
|
||||
EXPORTS_NAMESPACES = mozilla/dom mozilla
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
DirectionalityUtils.h \
|
||||
Element.h \
|
||||
FragmentOrElement.h \
|
||||
FromParser.h \
|
||||
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
96
content/base/src/DirectionalityUtils.cpp
Normal file
96
content/base/src/DirectionalityUtils.cpp
Normal 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
|
||||
|
@ -53,6 +53,7 @@ LOCAL_INCLUDES = \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
DirectionalityUtils.cpp \
|
||||
nsAtomListUtils.cpp \
|
||||
nsAttrAndChildArray.cpp \
|
||||
nsAttrValue.cpp \
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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 \
|
||||
|
44
content/base/test/test_bug562169-1.html
Normal file
44
content/base/test/test_bug562169-1.html
Normal 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>
|
29
content/base/test/test_bug562169-2.html
Normal file
29
content/base/test/test_bug562169-2.html
Normal 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>
|
@ -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!
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -2821,6 +2821,8 @@ void nsHTMLMediaElement::PlaybackEnded()
|
||||
return;
|
||||
}
|
||||
|
||||
Pause();
|
||||
|
||||
FireTimeUpdate(false);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ function seekStarted(evt) {
|
||||
function seekEnded(evt) {
|
||||
var v = evt.target;
|
||||
v._gotSeekEnded = true;
|
||||
v.play();
|
||||
}
|
||||
|
||||
function loadedData(evt) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
324
dom/contacts/tests/test_contacts_blobs.html
Normal file
324
dom/contacts/tests/test_contacts_blobs.html
Normal 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>
|
@ -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);
|
||||
|
@ -60,7 +60,8 @@ public:
|
||||
}
|
||||
|
||||
nsresult Init(nsIFile* aDirectory,
|
||||
mozIStorageConnection* aConnection);
|
||||
mozIStorageConnection* aConnection,
|
||||
FactoryPrivilege aPrivilege);
|
||||
|
||||
nsresult Load(mozIStorageConnection* aConnection);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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[]
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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;
|
||||
|
||||
|
@ -3,3 +3,8 @@
|
||||
b2g = true
|
||||
browser = false
|
||||
qemu = true
|
||||
|
||||
[test_mobile_voice_state.js]
|
||||
b2g = true
|
||||
browser = false
|
||||
qemu = true
|
||||
|
@ -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();
|
||||
|
115
dom/network/tests/marionette/test_mobile_voice_state.js
Normal file
115
dom/network/tests/marionette/test_mobile_voice_state.js
Normal 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();
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -85,6 +85,7 @@ MobileConnectionInfo.prototype = {
|
||||
// nsIDOMMozMobileConnectionInfo
|
||||
|
||||
connected: false,
|
||||
state: null,
|
||||
emergencyCallsOnly: false,
|
||||
roaming: false,
|
||||
network: null,
|
||||
|
@ -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) {
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user