From 35b4ff103c0279700a6d98cb07ab89d62877ebe8 Mon Sep 17 00:00:00 2001 From: Mike Shal Date: Wed, 13 Aug 2014 14:23:11 -0400 Subject: [PATCH 01/86] Bug 1047621 - Move link.py to config for importing expandlibs_exec; r=gps --- {build => config}/link.py | 0 toolkit/library/Makefile.in | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {build => config}/link.py (100%) diff --git a/build/link.py b/config/link.py similarity index 100% rename from build/link.py rename to config/link.py diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 1db2db0a3870..2e700edb6439 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -6,7 +6,7 @@ include $(topsrcdir)/toolkit/library/libxul.mk ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE)) # Wrap linker to measure peak virtual memory usage. -LD := $(PYTHON) $(topsrcdir)/build/link.py linker-vsize $(LD) +LD := $(PYTHON) $(topsrcdir)/config/link.py linker-vsize $(LD) endif include $(topsrcdir)/config/rules.mk From 21bbc49d68fb89312c6e18ec6e2c00eada8af9e8 Mon Sep 17 00:00:00 2001 From: Mike Shal Date: Wed, 13 Aug 2014 14:24:15 -0400 Subject: [PATCH 02/86] Bug 1047621 - Have link.py import and call expandlibs_exec.py; r=gps --- config/expandlibs_exec.py | 11 +++++++---- config/link.py | 29 ++++++++++++++++++----------- toolkit/library/Makefile.in | 4 +++- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/config/expandlibs_exec.py b/config/expandlibs_exec.py index 16017ae925d8..c05343022959 100644 --- a/config/expandlibs_exec.py +++ b/config/expandlibs_exec.py @@ -311,7 +311,7 @@ def print_command(out, args): print >>out, "".join([" " + l for l in file.readlines()]) out.flush() -def main(): +def main(args, proc_callback=None): parser = OptionParser() parser.add_option("--extract", action="store_true", dest="extract", help="when a library has no descriptor file, extract it first, when possible") @@ -322,7 +322,7 @@ def main(): parser.add_option("--symbol-order", dest="symbol_order", metavar="FILE", help="use the given list of symbols to order symbols in the resulting binary when using with a linker") - (options, args) = parser.parse_args() + (options, args) = parser.parse_args(args) with ExpandArgsMore(args) as args: if options.extract: @@ -336,6 +336,8 @@ def main(): print_command(sys.stderr, args) try: proc = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) + if proc_callback: + proc_callback(proc) except Exception, e: print >>sys.stderr, 'error: Launching', args, ':', e raise e @@ -345,7 +347,8 @@ def main(): sys.stderr.write(stdout) sys.stderr.flush() if proc.returncode: - exit(proc.returncode) + return proc.returncode + return 0 if __name__ == '__main__': - main() + exit(main(sys.argv[1:])) diff --git a/config/link.py b/config/link.py index b659f7eaba9c..57762803db2b 100644 --- a/config/link.py +++ b/config/link.py @@ -2,8 +2,11 @@ # 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/. -from __future__ import with_statement -import os, subprocess, sys, threading, time +import expandlibs_exec +import sys +import threading +import time + from win32 import procmem def measure_vsize_threadfunc(proc, output_file): @@ -33,14 +36,17 @@ def measure_link_vsize(output_file, args): Execute |args|, and measure the maximum virtual memory usage of the process, printing it to stdout when finished. """ - proc = subprocess.Popen(args) - t = threading.Thread(target=measure_vsize_threadfunc, - args=(proc, output_file)) - t.start() - # Wait for the linker to finish. - exitcode = proc.wait() - # ...and then wait for the background thread to finish. - t.join() + + # This needs to be a list in order for the callback to set the + # variable properly with python-2's scoping rules. + t = [None] + def callback(proc): + t[0] = threading.Thread(target=measure_vsize_threadfunc, + args=(proc, output_file)) + t[0].start() + exitcode = expandlibs_exec.main(args, proc_callback=callback) + # Wait for the background thread to finish. + t[0].join() return exitcode if __name__ == "__main__": @@ -50,4 +56,5 @@ if __name__ == "__main__": if len(sys.argv) < 3: print >>sys.stderr, "Usage: link.py " sys.exit(1) - sys.exit(measure_link_vsize(sys.argv[1], sys.argv[2:])) + output_file = sys.argv.pop(1) + sys.exit(measure_link_vsize(output_file, sys.argv[1:])) diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 2e700edb6439..580852b14fc3 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -4,9 +4,11 @@ include $(topsrcdir)/toolkit/library/libxul.mk +include $(topsrcdir)/config/config.mk + ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE)) # Wrap linker to measure peak virtual memory usage. -LD := $(PYTHON) $(topsrcdir)/config/link.py linker-vsize $(LD) +EXPAND_LIBS_EXEC := $(PYTHON) $(topsrcdir)/config/link.py linker-vsize endif include $(topsrcdir)/config/rules.mk From 434642061044bf698628e248adcd7a8db221e08d Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Fri, 15 Aug 2014 15:28:10 +0200 Subject: [PATCH 03/86] Bug 1054221 - [e10s] Make special link click behave correctly on about:newtab. r=jimm --- browser/base/content/browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 363b3bb45c7f..799ce84973eb 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2588,7 +2588,7 @@ let BrowserOnClick = { anchorTarget.classList.contains("newtab-link")) { event.preventDefault(); let where = whereToOpenLink(event, false, false); - openUILinkIn(anchorTarget.href, where); + openLinkIn(anchorTarget.href, where, { charset: ownerDoc.characterSet }); } }, From 80be244656684abe601e2062401455531910454b Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Fri, 15 Aug 2014 15:28:10 +0200 Subject: [PATCH 04/86] Bug 1037723 - Fix how the js shell global environment handles symbols. r=jandem --- js/src/shell/js.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 5f33e7193a5f..af2e49cfb2e8 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5058,8 +5058,12 @@ env_enumerate(JSContext *cx, HandleObject obj) static bool env_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp) { - RootedValue idvalue(cx, IdToValue(id)); - RootedString idstring(cx, ToString(cx, idvalue)); + if (JSID_IS_SYMBOL(id)) + return true; + + RootedString idstring(cx, IdToString(cx, id)); + if (!idstring) + return false; JSAutoByteString idstr; if (!idstr.encodeLatin1(cx, idstring)) return false; From 3f173be6a7f54964f74658854be19b7bec945b44 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Fri, 15 Aug 2014 15:28:10 +0200 Subject: [PATCH 05/86] Bug 1051611 - Remove error numbers from js.msg. r=jorendorff --- js/src/builtin/embedjs.py | 21 +- js/src/ctypes/CTypes.cpp | 2 +- js/src/ctypes/CTypes.h | 4 +- js/src/ctypes/ctypes.msg | 4 +- js/src/js.msg | 796 +++++++++++++++++++------------------- js/src/jsapi.cpp | 20 +- js/src/jscntxt.cpp | 2 +- js/src/jsfriendapi.h | 4 +- js/src/jsshell.msg | 38 +- js/src/shell/js.cpp | 6 +- 10 files changed, 437 insertions(+), 460 deletions(-) diff --git a/js/src/builtin/embedjs.py b/js/src/builtin/embedjs.py index fdb4e2e28ff2..a62f9221ebf5 100644 --- a/js/src/builtin/embedjs.py +++ b/js/src/builtin/embedjs.py @@ -78,14 +78,6 @@ namespace selfhosted { } // js """ -MSGS_TEMPLATE = """\ -#define hash # -#define id(x) x -#define hashify(x) id(hash)x -#define MSG_DEF(name, id, argc, ex, msg) hashify(define) name id -#include "%(msgs)s" -""" - def embed(cxx, preprocessorOption, msgs, sources, c_out, js_out, env): combinedSources = '\n'.join([msgs] + ['#include "%(s)s"' % { 's': source } for source in sources]) args = ['-D%(k)s=%(v)s' % { 'k': k, 'v': env[k] } for k in env] @@ -128,6 +120,17 @@ def preprocess(cxx, preprocessorOption, source, args = []): os.remove(tmpOut) return processed +def messages(jsmsg): + defines = [] + for line in open(jsmsg): + match = re.match("MSG_DEF\((JSMSG_(\w+))", line) + if match: + defines.append("#define %s %i" % (match.group(1), len(defines))) + else: + # Make sure that MSG_DEF isn't preceded by whitespace + assert not line.strip().startswith("MSG_DEF") + return '\n'.join(defines) + def main(): env = {} def define_env(option, opt, value, parser): @@ -152,7 +155,7 @@ def main(): p.print_help() sys.exit(1) cxx = shlex.split(options.c) - msgs = preprocess(cxx, options.p, MSGS_TEMPLATE % { 'msgs': options.m }) + msgs = messages(options.m) embed(cxx, options.p, msgs, sources, options.o, options.s, env) if __name__ == "__main__": diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 133279a3c5d6..2aa3b7a4a622 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -870,7 +870,7 @@ GetABICode(JSObject* obj) } static const JSErrorFormatString ErrorFormatString[CTYPESERR_LIMIT] = { -#define MSG_DEF(name, number, count, exception, format) \ +#define MSG_DEF(name, count, exception, format) \ { format, count, exception } , #include "ctypes/ctypes.msg" #undef MSG_DEF diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index 2635a3890644..4e57a7640a17 100644 --- a/js/src/ctypes/CTypes.h +++ b/js/src/ctypes/CTypes.h @@ -200,8 +200,8 @@ ASSERT_OK(bool ok) // for JS error reporting enum ErrorNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, +#define MSG_DEF(name, count, exception, format) \ + name, #include "ctypes/ctypes.msg" #undef MSG_DEF CTYPESERR_LIMIT diff --git a/js/src/ctypes/ctypes.msg b/js/src/ctypes/ctypes.msg index 6e598ad7841b..7178fcb26b3b 100644 --- a/js/src/ctypes/ctypes.msg +++ b/js/src/ctypes/ctypes.msg @@ -9,6 +9,6 @@ * For syntax details, see js/src/js.msg. */ -MSG_DEF(CTYPESMSG_PLACEHOLDER_0, 0, 0, JSEXN_NONE, NULL) -MSG_DEF(CTYPESMSG_TYPE_ERROR, 1, 2, JSEXN_TYPEERR, "expected type {0}, got {1}") +MSG_DEF(CTYPESMSG_PLACEHOLDER_0, 0, JSEXN_NONE, NULL) +MSG_DEF(CTYPESMSG_TYPE_ERROR, 2, JSEXN_TYPEERR, "expected type {0}, got {1}") diff --git a/js/src/js.msg b/js/src/js.msg index f24d12aa3459..43e65ad94980 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -9,15 +9,13 @@ * * The format for each JS error message is: * - * MSG_DEF(, , , , + * MSG_DEF(, , , * ) * * where ; * is a legal C identifer that will be used in the * JS engine source. * - * is an unique integral value identifying this error. - * * is an integer literal specifying the total number of * replaceable arguments in the following format string. * @@ -31,7 +29,7 @@ * * e.g. * - * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2, + * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 2, JSEXN_NONE, * "{0} is not a member of the {1} family") * * can be used: @@ -41,404 +39,396 @@ * to report: * * "Rhino is not a member of the Monkey family" - * - * When removing MSG_DEFs, convert them to JSMSG_UNUSED placeholders: - * - * MSG_DEF(JSMSG_UNUSED7, 7, 0, JSEXN_NONE, "") - * - * Before adding a new MSG_DEF at the end, look for existing JSMSG_UNUSED - * free index placeholders in the middle of the list. */ -MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") -MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined") -MSG_DEF(JSMSG_INACTIVE, 2, 0, JSEXN_INTERNALERR, "nothing active on context") -MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}") -MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_INTERNALERR, "invalid format character {0}") -MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_TYPEERR, "unknown type {0}") -MSG_DEF(JSMSG_ALLOC_OVERFLOW, 6, 0, JSEXN_INTERNALERR, "allocation size overflow") -MSG_DEF(JSMSG_MISSING_HEXDIGITS, 7, 0, JSEXN_SYNTAXERR, "missing hexadecimal digits after '0x'") -MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}") -MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_TYPEERR, "{0} has no constructor") -MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_TYPEERR, "can't alias {0} to {1} in class {2}") -MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 11, 1, JSEXN_TYPEERR, "{0} is not a scripted function") -MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument") -MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}") -MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals") -MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}") -MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}") -MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_INTERNALERR, "{0} too large") -MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 18, 0, JSEXN_ERR, "out of local root space") -MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_TYPEERR, "{0} is read-only") -MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter") -MSG_DEF(JSMSG_CANT_DELETE, 21, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted") -MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_TYPEERR, "{0} is not a function") -MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_TYPEERR, "{0} is not a constructor") -MSG_DEF(JSMSG_INVALID_DATE, 24, 0, JSEXN_RANGEERR, "invalid date") -MSG_DEF(JSMSG_TOO_DEEP, 25, 1, JSEXN_INTERNALERR, "{0} nested too deeply") -MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion") -MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}") -MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_TYPEERR, "invalid new expression result {0}") -MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED, 29, 0, JSEXN_ERR, "Permission denied to access object") -MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED, 30, 1, JSEXN_ERR, "Permission denied to access property '{0}'") -MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}") -MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}") -MSG_DEF(JSMSG_BAD_RADIX, 33, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36") -MSG_DEF(JSMSG_PAREN_BEFORE_LET, 34, 0, JSEXN_SYNTAXERR, "missing ( before let head") -MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_ERR, "can't convert {0} to an integer") -MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_TYPEERR, "cyclic {0} value") -MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 37, 0, JSEXN_TYPEERR, "can't compile over a script that is currently executing") -MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_TYPEERR, "can't convert {0} to {1}") -MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TYPEERR, "{0} has no properties") -MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_TYPEERR, "can't find class id {0}") -MSG_DEF(JSMSG_DEAD_OBJECT, 41, 0, JSEXN_TYPEERR, "can't access dead object") -MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})") -MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}") -MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments") -MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments") -MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 0, JSEXN_SYNTAXERR, "invalid quantifier") -MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}") -MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}") -MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum") -MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 50, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration") -MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 51, 0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator") -MSG_DEF(JSMSG_PAREN_AFTER_LET, 52, 0, JSEXN_SYNTAXERR, "missing ) after let head") -MSG_DEF(JSMSG_CURLY_AFTER_LET, 53, 0, JSEXN_SYNTAXERR, "missing } after let block") -MSG_DEF(JSMSG_MISSING_PAREN, 54, 0, JSEXN_SYNTAXERR, "unterminated parenthetical") -MSG_DEF(JSMSG_UNTERM_CLASS, 55, 0, JSEXN_SYNTAXERR, "unterminated character class") -MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression") -MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class") -MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}") -MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}") -MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}") -MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large") -MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression") -MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode") -MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range") -MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)") -MSG_DEF(JSMSG_SOURCE_TOO_LONG, 66, 0, JSEXN_RANGEERR, "source is too long") -MSG_DEF(JSMSG_BAD_WEAKMAP_KEY, 67, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key") -MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number") -MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters") -MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter") -MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters") -MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body") -MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body") -MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition") -MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition") -MSG_DEF(JSMSG_BAD_DUP_ARGS, 76, 0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context") -MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator") -MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression") -MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED, 79, 1, JSEXN_ERR, "Permission denied to define accessor property '{0}'") -MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression") -MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression") -MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body") -MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label") -MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body") -MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for") -MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer") -MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition") -MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control") -MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block") -MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block") -MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch") -MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch") -MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch") -MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block") -MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block") -MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block") -MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block") -MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try") -MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object") -MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object") -MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement") -MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name") -MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression") -MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list") -MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list") -MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id") -MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list") -MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical") -MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement") -MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR, 110, 0, JSEXN_SYNTAXERR, "missing } in template string") -MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}") -MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?") -MSG_DEF(JSMSG_OPTIMIZED_CLOSURE_LEAK, 113, 0, JSEXN_INTERNALERR, "can't access optimized closure") -MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default") -MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases") -MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement") -MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side") -MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_SYNTAXERR, "catch after unconditional catch") -MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try") -MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try") -MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found") -MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch") -MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "continue must be inside loop") -MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 124, 1, JSEXN_SYNTAXERR, "{0} not in function") -MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label") -MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label") -MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_TYPEERR, "variable {0} redeclares argument") -MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization") -MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_REFERENCEERR, "invalid assignment left-hand side") -MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand") -MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id") -MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier") -MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error") -MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 134, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'") -MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object") -MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent") -MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory") -MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal") -MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression") -MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment") -MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal") -MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 142, 0, JSEXN_TYPEERR, "bad cloned function scope chain") -MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 143, 0, JSEXN_SYNTAXERR, "missing octal digits after '0o'") -MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character") -MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant") -MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 146, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size") -MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught exception: {0}") -MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference") -MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses") -MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range") -MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_TYPEERR, "invalid {0} usage") -MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length") -MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}") -MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array") -MSG_DEF(JSMSG_REDECLARED_VAR, 155, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}") -MSG_DEF(JSMSG_UNDECLARED_VAR, 156, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}") -MSG_DEF(JSMSG_PROXY_REVOKED, 157, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy") -MSG_DEF(JSMSG_DEPRECATED_USAGE, 158, 1, JSEXN_REFERENCEERR, "deprecated {0} usage") -MSG_DEF(JSMSG_BAD_URI, 159, 0, JSEXN_URIERR, "malformed URI sequence") -MSG_DEF(JSMSG_GETTER_ONLY, 160, 0, JSEXN_TYPEERR, "setting a property that has only a getter") -MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 161, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal") -MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}") -MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression") -MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}") -MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another") -MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range") -MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals") -MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects") -MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 169, 0, JSEXN_SYNTAXERR, "too many catch variables") -MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 170, 0, JSEXN_RANGEERR, "repeat count must be non-negative") -MSG_DEF(JSMSG_INVALID_FOR_OF_INIT, 171, 0, JSEXN_SYNTAXERR, "for-of loop variable declaration may not have an initializer") -MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 172, 0, JSEXN_TYPEERR, "iterable for map should have array-like objects") -MSG_DEF(JSMSG_NOT_A_CODEPOINT, 173, 1, JSEXN_RANGEERR, "{0} is not a valid code point") -MSG_DEF(JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION, 174, 0, JSEXN_SYNTAXERR, "missing ] after array comprehension") -MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 0, JSEXN_TYPEERR, "already executing generator") -MSG_DEF(JSMSG_PAREN_AFTER_FOR_OF_ITERABLE, 176, 0, JSEXN_SYNTAXERR, "missing ) after for-of iterable") -MSG_DEF(JSMSG_INVALID_NORMALIZE_FORM, 177, 0, JSEXN_RANGEERR, "form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD'") -MSG_DEF(JSMSG_NOTHING_TO_REPEAT, 178, 0, JSEXN_SYNTAXERR, "nothing to repeat") -MSG_DEF(JSMSG_INVALID_GROUP, 179, 0, JSEXN_SYNTAXERR, "invalid regexp group") -MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 180, 0, JSEXN_SYNTAXERR, "\\ at end of pattern") -MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER, 181, 0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.") -MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator") -MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 183, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone") -MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 184, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone") -MSG_DEF(JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE, 185, 0, JSEXN_TYPEERR, "proxy can't report an extensible object as non-extensible") -MSG_DEF(JSMSG_SYMBOL_TO_STRING, 186, 0, JSEXN_TYPEERR, "can't convert symbol to string") -MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 187, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so") -MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") -MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 189, 0, JSEXN_TYPEERR, "can't convert symbol to number") -MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 190, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true") -MSG_DEF(JSMSG_BAD_INDEX, 191, 0, JSEXN_RANGEERR, "invalid or out-of-range index") -MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LET,192,0, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level 'let' declarations") -MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop") -MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED,194, 0, JSEXN_NONE, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead") -MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 195, 0, JSEXN_TYPEERR, "invalid arguments") -MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 196, 1, JSEXN_TYPEERR, "redeclaration of identifier '{0}' in catch") -MSG_DEF(JSMSG_INTERNAL_INTL_ERROR, 197, 0, JSEXN_ERR, "internal error while computing Intl data") -MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR, 198, 0, JSEXN_ERR, "internal error getting the default locale") -MSG_DEF(JSMSG_TOO_MANY_LOCALS, 199, 0, JSEXN_SYNTAXERR, "too many local variables") -MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large") -MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex") -MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 202, 0, JSEXN_INTERNALERR, "buffer too small") -MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate character {0}") -MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large") -MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}") -MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called") -MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}") -MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value") -MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value") -MSG_DEF(JSMSG_PROTO_SETTING_SLOW, 210, 0, JSEXN_NONE, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create") -MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for") -MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 212, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value") -MSG_DEF(JSMSG_OF_AFTER_FOR_NAME, 213, 0, JSEXN_SYNTAXERR, "missing 'of' after for") -MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}") -MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized") -MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side") -MSG_DEF(JSMSG_LET_COMP_BINDING, 217, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable") -MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value") -MSG_DEF(JSMSG_BAD_SYMBOL, 219, 1, JSEXN_TYPEERR, "{0} is not a well-known @@-symbol") -MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_REFERENCEERR, "invalid delete operand") -MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand") -MSG_DEF(JSMSG_UNEXPECTED_TYPE, 222, 2, JSEXN_TYPEERR, "{0} is {1}") -MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block") -MSG_DEF(JSMSG_CONTRARY_NONDIRECTIVE, 224, 1, JSEXN_SYNTAXERR, "'{0}' statement won't be enforced as a directive because it isn't in directive prologue position") -MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties") -MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter") -MSG_DEF(JSMSG_MISSING_FUN_ARG, 227, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}") -MSG_DEF(JSMSG_JSON_BAD_PARSE, 228, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data") -MSG_DEF(JSMSG_JSON_BAD_STRINGIFY, 229, 0, JSEXN_ERR, "JSON.stringify") -MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 230, 0, JSEXN_TYPEERR, "value is not a function or undefined") -MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 231, 0, JSEXN_TYPEERR, "value is not a non-null object") -MSG_DEF(JSMSG_DEPRECATED_OCTAL, 232, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated") -MSG_DEF(JSMSG_STRICT_CODE_WITH, 233, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements") -MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 234, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal") -MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 235, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated") -MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 236, 1, JSEXN_SYNTAXERR, "can't assign to {0} in strict mode") -MSG_DEF(JSMSG_BAD_BINDING, 237, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated") -MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 238, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified") -MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 239, 1, JSEXN_TYPEERR, "{0} is not extensible") -MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 240, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'") -MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 241, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable") -MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH,242, 0, JSEXN_TYPEERR, "can't redefine array length") -MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH,243, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length") -MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 244, 0, JSEXN_ERR, "invalid or out-of-range index") -MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG, 245, 1, JSEXN_ERR, "argument {0} must be >= 0") -MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 246, 0, JSEXN_ERR, "invalid arguments") -MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 247, 0, JSEXN_ERR, "call to Function() blocked by CSP") -MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 248, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function") -MSG_DEF(JSMSG_BAD_PROXY_FIX, 249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler") -MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument") -MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 251, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}") -MSG_DEF(JSMSG_THROW_TYPE_ERROR, 252, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them") -MSG_DEF(JSMSG_BAD_TOISOSTRING_PROP, 253, 0, JSEXN_TYPEERR, "toISOString property is not callable") -MSG_DEF(JSMSG_BAD_PARSE_NODE, 254, 0, JSEXN_INTERNALERR, "bad parse node") -MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 255, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}") -MSG_DEF(JSMSG_CALLER_IS_STRICT, 256, 0, JSEXN_TYPEERR, "access to strict mode caller function is censored") -MSG_DEF(JSMSG_NEED_DEBUG_MODE, 257, 0, JSEXN_ERR, "function can be called only in debug mode") -MSG_DEF(JSMSG_STRICT_CODE_LET_EXPR_STMT, 258, 0, JSEXN_ERR, "strict mode code may not contain unparenthesized let expression statements") -MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 259, 0, JSEXN_TYPEERR, "can't change object's extensibility") -MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 260, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})") -MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 261, 0, JSEXN_TYPEERR, "unsupported type for structured data") -MSG_DEF(JSMSG_SC_RECURSION, 262, 0, JSEXN_INTERNALERR, "recursive object") -MSG_DEF(JSMSG_DEBUG_CANT_DEBUG_GLOBAL, 263, 0, JSEXN_ERR, "passing non-debuggable global to addDebuggee") -MSG_DEF(JSMSG_BAD_CLONE_VERSION, 264, 0, JSEXN_ERR, "unsupported structured clone version") -MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 265, 0, JSEXN_TYPEERR, "can't clone object") -MSG_DEF(JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED, 266, 0, JSEXN_TYPEERR, "resumption values are disallowed in this hook") -MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 267, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function") -MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 268, 0, JSEXN_SYNTAXERR, "for-in loop let declaration may not have an initializer") -MSG_DEF(JSMSG_CLEARED_SCOPE, 269, 0, JSEXN_TYPEERR, "attempt to run compile-and-go script on a cleared scope") -MSG_DEF(JSMSG_MALFORMED_ESCAPE, 270, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence") -MSG_DEF(JSMSG_BAD_GENEXP_BODY, 271, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression") -MSG_DEF(JSMSG_YIELD_WITHOUT_OPERAND, 272, 0, JSEXN_SYNTAXERR, "yield without a value is deprecated, and illegal in ES6 (use 'yield undefined' instead)") -MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 273, 0, JSEXN_SYNTAXERR, "function statement requires a name") -MSG_DEF(JSMSG_CCW_REQUIRED, 274, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment") -MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 275, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null") -MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 276, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null") -MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 277, 1, JSEXN_ERR, "{0} is not live") -MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER, 278, 0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger") -MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 279, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object") -MSG_DEF(JSMSG_DEBUG_LOOP, 280, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger") -MSG_DEF(JSMSG_DEBUG_NOT_IDLE, 281, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack") -MSG_DEF(JSMSG_DEBUG_BAD_OFFSET, 282, 0, JSEXN_TYPEERR, "invalid script offset") -MSG_DEF(JSMSG_DEBUG_BAD_LINE, 283, 0, JSEXN_TYPEERR, "invalid line number") -MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 284, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee") -MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 285, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object") -MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 286, 0, JSEXN_ERR, "stack frame is not running JavaScript code") -MSG_DEF(JSMSG_CANT_WATCH_PROP, 287, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched") -MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 288, 0, JSEXN_ERR, "call to eval() blocked by CSP") -MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT, 289, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects") -MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 290, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?") -MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterable") -MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property") -MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties") -MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment") -MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter") -MSG_DEF(JSMSG_NO_REST_NAME, 296, 0, JSEXN_SYNTAXERR, "no parameter name after ...") -MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter") -MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used") -MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default") -MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default") -MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression") -MSG_DEF(JSMSG_INTRINSIC_NOT_DEFINED, 302, 1, JSEXN_REFERENCEERR, "no intrinsic function {0}") -MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 303, 2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one") -MSG_DEF(JSMSG_PAR_ARRAY_BAD_ARG, 304, 0, JSEXN_RANGEERR, "invalid parallel method argument") -MSG_DEF(JSMSG_REGEXP_RUNTIME_ERROR, 305, 0, JSEXN_INTERNALERR, "an error occurred while executing regular expression") -MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 306, 0, JSEXN_ERR, "variable has been optimized out") -MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE,307, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value") -MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_CONFLICT, 308, 0, JSEXN_ERR, "no conflict resolution function provided") -MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BOUNDS, 309, 0, JSEXN_ERR, "index in scatter vector out of bounds") -MSG_DEF(JSMSG_CANT_REPORT_NC_AS_NE, 310, 0, JSEXN_TYPEERR, "proxy can't report a non-configurable own property as non-existent") -MSG_DEF(JSMSG_CANT_REPORT_E_AS_NE, 311, 0, JSEXN_TYPEERR, "proxy can't report an existing own property as non-existent on a non-extensible object") -MSG_DEF(JSMSG_CANT_REPORT_NEW, 312, 0, JSEXN_TYPEERR, "proxy can't report a new property on a non-extensible object") -MSG_DEF(JSMSG_CANT_REPORT_INVALID, 313, 0, JSEXN_TYPEERR, "proxy can't report an incompatible property descriptor") -MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC, 314, 0, JSEXN_TYPEERR, "proxy can't report a non-existent property as non-configurable") -MSG_DEF(JSMSG_CANT_DEFINE_NEW, 315, 0, JSEXN_TYPEERR, "proxy can't define a new property on a non-extensible object") -MSG_DEF(JSMSG_CANT_DEFINE_INVALID, 316, 0, JSEXN_TYPEERR, "proxy can't define an incompatible property descriptor") -MSG_DEF(JSMSG_CANT_DEFINE_NE_AS_NC, 317, 0, JSEXN_TYPEERR, "proxy can't define a non-existent property as non-configurable") -MSG_DEF(JSMSG_INVALID_TRAP_RESULT, 318, 2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result") -MSG_DEF(JSMSG_CANT_SKIP_NC, 319, 0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property") -MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE, 320, 0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property") -MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 321, 0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter") -MSG_DEF(JSMSG_CANT_SET_NW_NC, 322, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property") -MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 323, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter") -MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 324, 2, JSEXN_TYPEERR, "{0} does not refer to {1}") -MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 325, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global object, but a direct reference is required") -MSG_DEF(JSMSG_UNWRAP_DENIED, 326, 0, JSEXN_ERR, "permission denied to unwrap object") -MSG_DEF(JSMSG_INTL_OBJECT_NOT_INITED, 327, 3, JSEXN_TYPEERR, "Intl.{0}.prototype.{1} called on value that's not an object initialized as a {2}") -MSG_DEF(JSMSG_INVALID_LOCALES_ELEMENT,328, 0, JSEXN_TYPEERR, "invalid element in locales argument") -MSG_DEF(JSMSG_INVALID_LANGUAGE_TAG, 329, 1, JSEXN_RANGEERR, "invalid language tag: {0}") -MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 330, 1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}") -MSG_DEF(JSMSG_INVALID_OPTION_VALUE, 331, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}") -MSG_DEF(JSMSG_INVALID_DIGITS_VALUE, 332, 1, JSEXN_RANGEERR, "invalid digits value: {0}") -MSG_DEF(JSMSG_INTL_OBJECT_REINITED, 333, 0, JSEXN_TYPEERR, "can't initialize object twice as an object of an Intl constructor") -MSG_DEF(JSMSG_INVALID_CURRENCY_CODE, 334, 1, JSEXN_RANGEERR, "invalid currency code in NumberFormat(): {0}") -MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 335, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style") -MSG_DEF(JSMSG_INVALID_TIME_ZONE, 336, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}") -MSG_DEF(JSMSG_DATE_NOT_FINITE, 337, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()") -MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 338, 0, JSEXN_SYNTAXERR, "\"use asm\" is only meaningful in the Directive Prologue of a function body") -MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 339, 1, JSEXN_TYPEERR, "asm.js type error: {0}") -MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 340, 1, JSEXN_TYPEERR, "asm.js link error: {0}") -MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 341, 1, JSEXN_NONE, "Successfully compiled asm.js code ({0})") -MSG_DEF(JSMSG_BAD_ARROW_ARGS, 342, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)") -MSG_DEF(JSMSG_YIELD_IN_ARROW, 343, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield") -MSG_DEF(JSMSG_WRONG_VALUE, 344, 2, JSEXN_ERR, "expected {0} but found {1}") -MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, 345, 1, JSEXN_ERR, "target for index {0} is not an integer") -MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME,346, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups") -MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 347, 1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead") -MSG_DEF(JSMSG_BAD_DESTRUCT_ASSIGN, 348, 1, JSEXN_SYNTAXERR, "can't assign to {0} using destructuring assignment") -MSG_DEF(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS, 349, 0, JSEXN_ERR, "Invalid arguments") -MSG_DEF(JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX, 350, 0, JSEXN_RANGEERR, "invalid or out-of-range index") -MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 351, 0, JSEXN_RANGEERR, "invalid field descriptor") -MSG_DEF(JSMSG_TYPEDOBJECT_NOT_BINARYSTRUCT, 352, 1, JSEXN_TYPEERR, "{0} is not a BinaryStruct") -MSG_DEF(JSMSG_TYPEDOBJECT_SUBARRAY_INTEGER_ARG, 353, 1, JSEXN_ERR, "argument {0} must be an integer") -MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_EMPTY_DESCRIPTOR, 354, 0, JSEXN_ERR, "field descriptor cannot be empty") -MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_FIELD, 355, 1, JSEXN_ERR, "field {0} is not a valid BinaryData Type descriptor") -MSG_DEF(JSMSG_GENERATOR_FINISHED, 356, 0, JSEXN_TYPEERR, "generator has already finished") -MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 357, 0, JSEXN_ERR, "Type is too large to allocate") -MSG_DEF(JSMSG_TYPEDOBJECT_NOT_TYPE_OBJECT, 358, 0, JSEXN_ERR, "Expected a type object") -MSG_DEF(JSMSG_TOO_MANY_CON_SPREADARGS, 359, 0, JSEXN_RANGEERR, "too many constructor arguments") -MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 360, 0, JSEXN_RANGEERR, "too many function arguments") -MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGEE, 361, 2, JSEXN_ERR, "{0} is not a debuggee {1}") -MSG_DEF(JSMSG_TYPEDOBJECT_NOT_TYPED_OBJECT, 362, 0, JSEXN_ERR, "Expected a typed object") -MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, 363, 1, JSEXN_TYPEERR, "No such property: {0}") -MSG_DEF(JSMSG_TYPEDOBJECT_BAD_ARGS, 364, 0, JSEXN_TYPEERR, "invalid arguments") -MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 365, 0, JSEXN_TYPEERR, "handle unattached") -MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 366, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type") - -MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 367, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level") -MSG_DEF(JSMSG_NO_IMPORT_NAME, 368, 0, JSEXN_SYNTAXERR, "missing import name") -MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 369, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'") -MSG_DEF(JSMSG_NO_BINDING_NAME, 370, 0, JSEXN_SYNTAXERR, "missing binding name") -MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 371, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list") -MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 372, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set") -MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT, 373, 0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword") -MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 374, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword") -MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED, 375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet") -MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL, 376, 0, JSEXN_SYNTAXERR, "export declarations may only appear at top level") -MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 377, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list") -MSG_DEF(JSMSG_NO_EXPORT_NAME, 378, 0, JSEXN_SYNTAXERR, "missing export name") -MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT, 379, 0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword") -MSG_DEF(JSMSG_INVALID_PROTOTYPE, 380, 0, JSEXN_TYPEERR, "prototype field is not an object") -MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type") -MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 382, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}") -MSG_DEF(JSMSG_INVALID_ARG_TYPE, 383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}") -MSG_DEF(JSMSG_TERMINATED, 384, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}") -MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP, 385, 1, JSEXN_ERR, "No such property on self-hosted object: {0}") -MSG_DEF(JSMSG_PROXY_EXTENSIBILITY, 386, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target") -MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT, 387, 0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object") -MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 388, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined") -MSG_DEF(JSMSG_CANT_REPORT_C_AS_NC, 389, 0, JSEXN_TYPEERR, "proxy can't report existing configurable property as non-configurable") -MSG_DEF(JSMSG_COMP_PROP_UNTERM_EXPR, 390, 0, JSEXN_SYNTAXERR, "missing ] in computed property name") +MSG_DEF(JSMSG_NOT_AN_ERROR, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_NOT_DEFINED, 1, JSEXN_REFERENCEERR, "{0} is not defined") +MSG_DEF(JSMSG_INACTIVE, 0, JSEXN_INTERNALERR, "nothing active on context") +MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}") +MSG_DEF(JSMSG_BAD_CHAR, 1, JSEXN_INTERNALERR, "invalid format character {0}") +MSG_DEF(JSMSG_BAD_TYPE, 1, JSEXN_TYPEERR, "unknown type {0}") +MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size overflow") +MSG_DEF(JSMSG_MISSING_HEXDIGITS, 0, JSEXN_SYNTAXERR, "missing hexadecimal digits after '0x'") +MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}") +MSG_DEF(JSMSG_NO_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} has no constructor") +MSG_DEF(JSMSG_CANT_ALIAS, 3, JSEXN_TYPEERR, "can't alias {0} to {1} in class {2}") +MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a scripted function") +MSG_DEF(JSMSG_BAD_SORT_ARG, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument") +MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}") +MSG_DEF(JSMSG_TOO_MANY_LITERALS, 0, JSEXN_INTERNALERR, "too many literals") +MSG_DEF(JSMSG_CANT_WATCH, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}") +MSG_DEF(JSMSG_STACK_UNDERFLOW, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}") +MSG_DEF(JSMSG_NEED_DIET, 1, JSEXN_INTERNALERR, "{0} too large") +MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 0, JSEXN_ERR, "out of local root space") +MSG_DEF(JSMSG_READ_ONLY, 1, JSEXN_TYPEERR, "{0} is read-only") +MSG_DEF(JSMSG_BAD_FORMAL, 0, JSEXN_SYNTAXERR, "malformed formal parameter") +MSG_DEF(JSMSG_CANT_DELETE, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted") +MSG_DEF(JSMSG_NOT_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a function") +MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor") +MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date") +MSG_DEF(JSMSG_TOO_DEEP, 1, JSEXN_INTERNALERR, "{0} nested too deeply") +MSG_DEF(JSMSG_OVER_RECURSED, 0, JSEXN_INTERNALERR, "too much recursion") +MSG_DEF(JSMSG_IN_NOT_OBJECT, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}") +MSG_DEF(JSMSG_BAD_NEW_RESULT, 1, JSEXN_TYPEERR, "invalid new expression result {0}") +MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED, 0, JSEXN_ERR, "Permission denied to access object") +MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED, 1, JSEXN_ERR, "Permission denied to access property '{0}'") +MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}") +MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}") +MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36") +MSG_DEF(JSMSG_PAREN_BEFORE_LET, 0, JSEXN_SYNTAXERR, "missing ( before let head") +MSG_DEF(JSMSG_CANT_CONVERT, 1, JSEXN_ERR, "can't convert {0} to an integer") +MSG_DEF(JSMSG_CYCLIC_VALUE, 1, JSEXN_TYPEERR, "cyclic {0} value") +MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 0, JSEXN_TYPEERR, "can't compile over a script that is currently executing") +MSG_DEF(JSMSG_CANT_CONVERT_TO, 2, JSEXN_TYPEERR, "can't convert {0} to {1}") +MSG_DEF(JSMSG_NO_PROPERTIES, 1, JSEXN_TYPEERR, "{0} has no properties") +MSG_DEF(JSMSG_CANT_FIND_CLASS, 1, JSEXN_TYPEERR, "can't find class id {0}") +MSG_DEF(JSMSG_DEAD_OBJECT, 0, JSEXN_TYPEERR, "can't access dead object") +MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})") +MSG_DEF(JSMSG_UNKNOWN_FORMAT, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}") +MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 0, JSEXN_SYNTAXERR, "too many constructor arguments") +MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 0, JSEXN_SYNTAXERR, "too many function arguments") +MSG_DEF(JSMSG_BAD_QUANTIFIER, 0, JSEXN_SYNTAXERR, "invalid quantifier") +MSG_DEF(JSMSG_MIN_TOO_BIG, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}") +MSG_DEF(JSMSG_MAX_TOO_BIG, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}") +MSG_DEF(JSMSG_OUT_OF_ORDER, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum") +MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration") +MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator") +MSG_DEF(JSMSG_PAREN_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing ) after let head") +MSG_DEF(JSMSG_CURLY_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing } after let block") +MSG_DEF(JSMSG_MISSING_PAREN, 0, JSEXN_SYNTAXERR, "unterminated parenthetical") +MSG_DEF(JSMSG_UNTERM_CLASS, 0, JSEXN_SYNTAXERR, "unterminated character class") +MSG_DEF(JSMSG_TRAILING_SLASH, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression") +MSG_DEF(JSMSG_BAD_CLASS_RANGE, 0, JSEXN_SYNTAXERR, "invalid range in character class") +MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}") +MSG_DEF(JSMSG_NO_INPUT, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}") +MSG_DEF(JSMSG_CANT_OPEN, 2, JSEXN_ERR, "can't open {0}: {1}") +MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large") +MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression") +MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 0, JSEXN_INTERNALERR, "data are to big to encode") +MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range") +MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)") +MSG_DEF(JSMSG_SOURCE_TOO_LONG, 0, JSEXN_RANGEERR, "source is too long") +MSG_DEF(JSMSG_BAD_WEAKMAP_KEY, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key") +MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 0, JSEXN_INTERNALERR, "bad script XDR magic number") +MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters") +MSG_DEF(JSMSG_MISSING_FORMAL, 0, JSEXN_SYNTAXERR, "missing formal parameter") +MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters") +MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 0, JSEXN_SYNTAXERR, "missing { before function body") +MSG_DEF(JSMSG_CURLY_AFTER_BODY, 0, JSEXN_SYNTAXERR, "missing } after function body") +MSG_DEF(JSMSG_PAREN_BEFORE_COND, 0, JSEXN_SYNTAXERR, "missing ( before condition") +MSG_DEF(JSMSG_PAREN_AFTER_COND, 0, JSEXN_SYNTAXERR, "missing ) after condition") +MSG_DEF(JSMSG_BAD_DUP_ARGS, 0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context") +MSG_DEF(JSMSG_NAME_AFTER_DOT, 0, JSEXN_SYNTAXERR, "missing name after . operator") +MSG_DEF(JSMSG_BRACKET_IN_INDEX, 0, JSEXN_SYNTAXERR, "missing ] in index expression") +MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED, 1, JSEXN_ERR, "Permission denied to define accessor property '{0}'") +MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing ( before switch expression") +MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 0, JSEXN_SYNTAXERR, "missing ) after switch expression") +MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing { before switch body") +MSG_DEF(JSMSG_COLON_AFTER_CASE, 0, JSEXN_SYNTAXERR, "missing : after case label") +MSG_DEF(JSMSG_WHILE_AFTER_DO, 0, JSEXN_SYNTAXERR, "missing while after do-loop body") +MSG_DEF(JSMSG_PAREN_AFTER_FOR, 0, JSEXN_SYNTAXERR, "missing ( after for") +MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer") +MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition") +MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control") +MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 0, JSEXN_SYNTAXERR, "missing { before try block") +MSG_DEF(JSMSG_CURLY_AFTER_TRY, 0, JSEXN_SYNTAXERR, "missing } after try block") +MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing ( before catch") +MSG_DEF(JSMSG_CATCH_IDENTIFIER, 0, JSEXN_SYNTAXERR, "missing identifier in catch") +MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing ) after catch") +MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing { before catch block") +MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing } after catch block") +MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 0, JSEXN_SYNTAXERR, "missing { before finally block") +MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 0, JSEXN_SYNTAXERR, "missing } after finally block") +MSG_DEF(JSMSG_CATCH_OR_FINALLY, 0, JSEXN_SYNTAXERR, "missing catch or finally after try") +MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object") +MSG_DEF(JSMSG_PAREN_AFTER_WITH, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object") +MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 0, JSEXN_SYNTAXERR, "missing } in compound statement") +MSG_DEF(JSMSG_NO_VARIABLE_NAME, 0, JSEXN_SYNTAXERR, "missing variable name") +MSG_DEF(JSMSG_COLON_IN_COND, 0, JSEXN_SYNTAXERR, "missing : in conditional expression") +MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 0, JSEXN_SYNTAXERR, "missing ) after argument list") +MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 0, JSEXN_SYNTAXERR, "missing ] after element list") +MSG_DEF(JSMSG_COLON_AFTER_ID, 0, JSEXN_SYNTAXERR, "missing : after property id") +MSG_DEF(JSMSG_CURLY_AFTER_LIST, 0, JSEXN_SYNTAXERR, "missing } after property list") +MSG_DEF(JSMSG_PAREN_IN_PAREN, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical") +MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement") +MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing } in template string") +MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}") +MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?") +MSG_DEF(JSMSG_OPTIMIZED_CLOSURE_LEAK, 0, JSEXN_INTERNALERR, "can't access optimized closure") +MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 0, JSEXN_SYNTAXERR, "more than one switch default") +MSG_DEF(JSMSG_TOO_MANY_CASES, 0, JSEXN_INTERNALERR, "too many switch cases") +MSG_DEF(JSMSG_BAD_SWITCH, 0, JSEXN_SYNTAXERR, "invalid switch statement") +MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side") +MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 0, JSEXN_SYNTAXERR, "catch after unconditional catch") +MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "catch without try") +MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "finally without try") +MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found") +MSG_DEF(JSMSG_TOUGH_BREAK, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch") +MSG_DEF(JSMSG_BAD_CONTINUE, 0, JSEXN_SYNTAXERR, "continue must be inside loop") +MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function") +MSG_DEF(JSMSG_BAD_LABEL, 0, JSEXN_SYNTAXERR, "invalid label") +MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label") +MSG_DEF(JSMSG_VAR_HIDES_ARG, 1, JSEXN_TYPEERR, "variable {0} redeclares argument") +MSG_DEF(JSMSG_BAD_VAR_INIT, 0, JSEXN_SYNTAXERR, "invalid variable initialization") +MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_REFERENCEERR, "invalid assignment left-hand side") +MSG_DEF(JSMSG_BAD_OPERAND, 1, JSEXN_SYNTAXERR, "invalid {0} operand") +MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id") +MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier") +MSG_DEF(JSMSG_SYNTAX_ERROR, 0, JSEXN_SYNTAXERR, "syntax error") +MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'") +MSG_DEF(JSMSG_BAD_PROTOTYPE, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object") +MSG_DEF(JSMSG_MISSING_EXPONENT, 0, JSEXN_SYNTAXERR, "missing exponent") +MSG_DEF(JSMSG_OUT_OF_MEMORY, 0, JSEXN_ERR, "out of memory") +MSG_DEF(JSMSG_UNTERMINATED_STRING, 0, JSEXN_SYNTAXERR, "unterminated string literal") +MSG_DEF(JSMSG_TOO_MANY_PARENS, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression") +MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 0, JSEXN_SYNTAXERR, "unterminated comment") +MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal") +MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 0, JSEXN_TYPEERR, "bad cloned function scope chain") +MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 0, JSEXN_SYNTAXERR, "missing octal digits after '0o'") +MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character") +MSG_DEF(JSMSG_BAD_OCTAL, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant") +MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size") +MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 1, JSEXN_INTERNALERR, "uncaught exception: {0}") +MSG_DEF(JSMSG_INVALID_BACKREF, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference") +MSG_DEF(JSMSG_BAD_BACKREF, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses") +MSG_DEF(JSMSG_PRECISION_RANGE, 1, JSEXN_RANGEERR, "precision {0} out of range") +MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 1, JSEXN_TYPEERR, "invalid {0} usage") +MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 0, JSEXN_RANGEERR, "invalid array length") +MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}") +MSG_DEF(JSMSG_BAD_APPLY_ARGS, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array") +MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}") +MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}") +MSG_DEF(JSMSG_PROXY_REVOKED, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy") +MSG_DEF(JSMSG_DEPRECATED_USAGE, 1, JSEXN_REFERENCEERR, "deprecated {0} usage") +MSG_DEF(JSMSG_BAD_URI, 0, JSEXN_URIERR, "malformed URI sequence") +MSG_DEF(JSMSG_GETTER_ONLY, 0, JSEXN_TYPEERR, "setting a property that has only a getter") +MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal") +MSG_DEF(JSMSG_UNDEFINED_PROP, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}") +MSG_DEF(JSMSG_USELESS_EXPR, 0, JSEXN_TYPEERR, "useless expression") +MSG_DEF(JSMSG_REDECLARED_PARAM, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}") +MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another") +MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 0, JSEXN_RANGEERR, "reserved slot index out of range") +MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals") +MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 1, JSEXN_ERR, "can't seal {0} objects") +MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 0, JSEXN_SYNTAXERR, "too many catch variables") +MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative") +MSG_DEF(JSMSG_INVALID_FOR_OF_INIT, 0, JSEXN_SYNTAXERR, "for-of loop variable declaration may not have an initializer") +MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 0, JSEXN_TYPEERR, "iterable for map should have array-like objects") +MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point") +MSG_DEF(JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION, 0, JSEXN_SYNTAXERR, "missing ] after array comprehension") +MSG_DEF(JSMSG_NESTING_GENERATOR, 0, JSEXN_TYPEERR, "already executing generator") +MSG_DEF(JSMSG_PAREN_AFTER_FOR_OF_ITERABLE, 0, JSEXN_SYNTAXERR, "missing ) after for-of iterable") +MSG_DEF(JSMSG_INVALID_NORMALIZE_FORM, 0, JSEXN_RANGEERR, "form must be one of 'NFC', 'NFD', 'NFKC', or 'NFKD'") +MSG_DEF(JSMSG_NOTHING_TO_REPEAT, 0, JSEXN_SYNTAXERR, "nothing to repeat") +MSG_DEF(JSMSG_INVALID_GROUP, 0, JSEXN_SYNTAXERR, "invalid regexp group") +MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern") +MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER, 0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.") +MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator") +MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone") +MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone") +MSG_DEF(JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE, 0, JSEXN_TYPEERR, "proxy can't report an extensible object as non-extensible") +MSG_DEF(JSMSG_SYMBOL_TO_STRING, 0, JSEXN_TYPEERR, "can't convert symbol to string") +MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so") +MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") +MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol to number") +MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true") +MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index") +MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LET,0, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level 'let' declarations") +MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loop") +MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_NONE, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead") +MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments") +MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_TYPEERR, "redeclaration of identifier '{0}' in catch") +MSG_DEF(JSMSG_INTERNAL_INTL_ERROR, 0, JSEXN_ERR, "internal error while computing Intl data") +MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR, 0, JSEXN_ERR, "internal error getting the default locale") +MSG_DEF(JSMSG_TOO_MANY_LOCALS, 0, JSEXN_SYNTAXERR, "too many local variables") +MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initialiser too large") +MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 0, JSEXN_INTERNALERR, "regular expression too complex") +MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small") +MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 1, JSEXN_TYPEERR, "bad surrogate character {0}") +MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large") +MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}") +MSG_DEF(JSMSG_USER_DEFINED_ERROR, 0, JSEXN_ERR, "JS_ReportError was called") +MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 1, JSEXN_TYPEERR, "wrong constructor called for {0}") +MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value") +MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value") +MSG_DEF(JSMSG_PROTO_SETTING_SLOW, 0, JSEXN_NONE, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create") +MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for") +MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value") +MSG_DEF(JSMSG_OF_AFTER_FOR_NAME, 0, JSEXN_SYNTAXERR, "missing 'of' after for") +MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 1, JSEXN_TYPEERR, "yield from closing generator {0}") +MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized") +MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side") +MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable") +MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value") +MSG_DEF(JSMSG_BAD_SYMBOL, 1, JSEXN_TYPEERR, "{0} is not a well-known @@-symbol") +MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 0, JSEXN_REFERENCEERR, "invalid delete operand") +MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand") +MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}") +MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 0, JSEXN_SYNTAXERR, "let declaration not directly within block") +MSG_DEF(JSMSG_CONTRARY_NONDIRECTIVE, 1, JSEXN_SYNTAXERR, "'{0}' statement won't be enforced as a directive because it isn't in directive prologue position") +MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties") +MSG_DEF(JSMSG_EVAL_ARITY, 0, JSEXN_TYPEERR, "eval accepts only one parameter") +MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}") +MSG_DEF(JSMSG_JSON_BAD_PARSE, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data") +MSG_DEF(JSMSG_JSON_BAD_STRINGIFY, 0, JSEXN_ERR, "JSON.stringify") +MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined") +MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 0, JSEXN_TYPEERR, "value is not a non-null object") +MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated") +MSG_DEF(JSMSG_STRICT_CODE_WITH, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements") +MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal") +MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated") +MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "can't assign to {0} in strict mode") +MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated") +MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified") +MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0} is not extensible") +MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'") +MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable") +MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length") +MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length") +MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 0, JSEXN_ERR, "invalid or out-of-range index") +MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_ERR, "argument {0} must be >= 0") +MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_ERR, "invalid arguments") +MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 0, JSEXN_ERR, "call to Function() blocked by CSP") +MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function") +MSG_DEF(JSMSG_BAD_PROXY_FIX, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler") +MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 0, JSEXN_EVALERR, "invalid eval scope argument") +MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}") +MSG_DEF(JSMSG_THROW_TYPE_ERROR, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them") +MSG_DEF(JSMSG_BAD_TOISOSTRING_PROP, 0, JSEXN_TYPEERR, "toISOString property is not callable") +MSG_DEF(JSMSG_BAD_PARSE_NODE, 0, JSEXN_INTERNALERR, "bad parse node") +MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}") +MSG_DEF(JSMSG_CALLER_IS_STRICT, 0, JSEXN_TYPEERR, "access to strict mode caller function is censored") +MSG_DEF(JSMSG_NEED_DEBUG_MODE, 0, JSEXN_ERR, "function can be called only in debug mode") +MSG_DEF(JSMSG_STRICT_CODE_LET_EXPR_STMT, 0, JSEXN_ERR, "strict mode code may not contain unparenthesized let expression statements") +MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 0, JSEXN_TYPEERR, "can't change object's extensibility") +MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})") +MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data") +MSG_DEF(JSMSG_SC_RECURSION, 0, JSEXN_INTERNALERR, "recursive object") +MSG_DEF(JSMSG_DEBUG_CANT_DEBUG_GLOBAL, 0, JSEXN_ERR, "passing non-debuggable global to addDebuggee") +MSG_DEF(JSMSG_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clone version") +MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 0, JSEXN_TYPEERR, "can't clone object") +MSG_DEF(JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED, 0, JSEXN_TYPEERR, "resumption values are disallowed in this hook") +MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function") +MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 0, JSEXN_SYNTAXERR, "for-in loop let declaration may not have an initializer") +MSG_DEF(JSMSG_CLEARED_SCOPE, 0, JSEXN_TYPEERR, "attempt to run compile-and-go script on a cleared scope") +MSG_DEF(JSMSG_MALFORMED_ESCAPE, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence") +MSG_DEF(JSMSG_BAD_GENEXP_BODY, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression") +MSG_DEF(JSMSG_YIELD_WITHOUT_OPERAND, 0, JSEXN_SYNTAXERR, "yield without a value is deprecated, and illegal in ES6 (use 'yield undefined' instead)") +MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 0, JSEXN_SYNTAXERR, "function statement requires a name") +MSG_DEF(JSMSG_CCW_REQUIRED, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment") +MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null") +MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null") +MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 1, JSEXN_ERR, "{0} is not live") +MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER,0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger") +MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object") +MSG_DEF(JSMSG_DEBUG_LOOP, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger") +MSG_DEF(JSMSG_DEBUG_NOT_IDLE, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack") +MSG_DEF(JSMSG_DEBUG_BAD_OFFSET, 0, JSEXN_TYPEERR, "invalid script offset") +MSG_DEF(JSMSG_DEBUG_BAD_LINE, 0, JSEXN_TYPEERR, "invalid line number") +MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee") +MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object") +MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 0, JSEXN_ERR, "stack frame is not running JavaScript code") +MSG_DEF(JSMSG_CANT_WATCH_PROP, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched") +MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 0, JSEXN_ERR, "call to eval() blocked by CSP") +MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects") +MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?") +MSG_DEF(JSMSG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable") +MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property") +MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties") +MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND,0, JSEXN_TYPEERR, "variable not found in environment") +MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 0, JSEXN_SYNTAXERR, "parameter after rest parameter") +MSG_DEF(JSMSG_NO_REST_NAME, 0, JSEXN_SYNTAXERR, "no parameter name after ...") +MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter") +MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used") +MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default") +MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default") +MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "yield in default expression") +MSG_DEF(JSMSG_INTRINSIC_NOT_DEFINED, 1, JSEXN_REFERENCEERR, "no intrinsic function {0}") +MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one") +MSG_DEF(JSMSG_PAR_ARRAY_BAD_ARG, 0, JSEXN_RANGEERR, "invalid parallel method argument") +MSG_DEF(JSMSG_REGEXP_RUNTIME_ERROR, 0, JSEXN_INTERNALERR, "an error occurred while executing regular expression") +MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 0, JSEXN_ERR, "variable has been optimized out") +MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value") +MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_CONFLICT, 0, JSEXN_ERR, "no conflict resolution function provided") +MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BOUNDS,0, JSEXN_ERR, "index in scatter vector out of bounds") +MSG_DEF(JSMSG_CANT_REPORT_NC_AS_NE, 0, JSEXN_TYPEERR, "proxy can't report a non-configurable own property as non-existent") +MSG_DEF(JSMSG_CANT_REPORT_E_AS_NE, 0, JSEXN_TYPEERR, "proxy can't report an existing own property as non-existent on a non-extensible object") +MSG_DEF(JSMSG_CANT_REPORT_NEW, 0, JSEXN_TYPEERR, "proxy can't report a new property on a non-extensible object") +MSG_DEF(JSMSG_CANT_REPORT_INVALID, 0, JSEXN_TYPEERR, "proxy can't report an incompatible property descriptor") +MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC, 0, JSEXN_TYPEERR, "proxy can't report a non-existent property as non-configurable") +MSG_DEF(JSMSG_CANT_DEFINE_NEW, 0, JSEXN_TYPEERR, "proxy can't define a new property on a non-extensible object") +MSG_DEF(JSMSG_CANT_DEFINE_INVALID, 0, JSEXN_TYPEERR, "proxy can't define an incompatible property descriptor") +MSG_DEF(JSMSG_CANT_DEFINE_NE_AS_NC, 0, JSEXN_TYPEERR, "proxy can't define a non-existent property as non-configurable") +MSG_DEF(JSMSG_INVALID_TRAP_RESULT, 2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result") +MSG_DEF(JSMSG_CANT_SKIP_NC, 0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property") +MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE, 0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property") +MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter") +MSG_DEF(JSMSG_CANT_SET_NW_NC, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property") +MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter") +MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 2, JSEXN_TYPEERR, "{0} does not refer to {1}") +MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global object, but a direct reference is required") +MSG_DEF(JSMSG_UNWRAP_DENIED, 0, JSEXN_ERR, "permission denied to unwrap object") +MSG_DEF(JSMSG_INTL_OBJECT_NOT_INITED, 3, JSEXN_TYPEERR, "Intl.{0}.prototype.{1} called on value that's not an object initialized as a {2}") +MSG_DEF(JSMSG_INVALID_LOCALES_ELEMENT, 0, JSEXN_TYPEERR, "invalid element in locales argument") +MSG_DEF(JSMSG_INVALID_LANGUAGE_TAG, 1, JSEXN_RANGEERR, "invalid language tag: {0}") +MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}") +MSG_DEF(JSMSG_INVALID_OPTION_VALUE, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}") +MSG_DEF(JSMSG_INVALID_DIGITS_VALUE, 1, JSEXN_RANGEERR, "invalid digits value: {0}") +MSG_DEF(JSMSG_INTL_OBJECT_REINITED, 0, JSEXN_TYPEERR, "can't initialize object twice as an object of an Intl constructor") +MSG_DEF(JSMSG_INVALID_CURRENCY_CODE, 1, JSEXN_RANGEERR, "invalid currency code in NumberFormat(): {0}") +MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style") +MSG_DEF(JSMSG_INVALID_TIME_ZONE, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}") +MSG_DEF(JSMSG_DATE_NOT_FINITE, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()") +MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 0, JSEXN_SYNTAXERR, "\"use asm\" is only meaningful in the Directive Prologue of a function body") +MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}") +MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 1, JSEXN_TYPEERR, "asm.js link error: {0}") +MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 1, JSEXN_NONE, "Successfully compiled asm.js code ({0})") +MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)") +MSG_DEF(JSMSG_YIELD_IN_ARROW, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield") +MSG_DEF(JSMSG_WRONG_VALUE, 2, JSEXN_ERR, "expected {0} but found {1}") +MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, 1, JSEXN_ERR, "target for index {0} is not an integer") +MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups") +MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead") +MSG_DEF(JSMSG_BAD_DESTRUCT_ASSIGN, 1, JSEXN_SYNTAXERR, "can't assign to {0} using destructuring assignment") +MSG_DEF(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS, 0, JSEXN_ERR, "Invalid arguments") +MSG_DEF(JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index") +MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor") +MSG_DEF(JSMSG_TYPEDOBJECT_NOT_BINARYSTRUCT, 1, JSEXN_TYPEERR, "{0} is not a BinaryStruct") +MSG_DEF(JSMSG_TYPEDOBJECT_SUBARRAY_INTEGER_ARG, 1, JSEXN_ERR, "argument {0} must be an integer") +MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_EMPTY_DESCRIPTOR, 0, JSEXN_ERR, "field descriptor cannot be empty") +MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_FIELD, 1, JSEXN_ERR, "field {0} is not a valid BinaryData Type descriptor") +MSG_DEF(JSMSG_GENERATOR_FINISHED, 0, JSEXN_TYPEERR, "generator has already finished") +MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate") +MSG_DEF(JSMSG_TYPEDOBJECT_NOT_TYPE_OBJECT, 0, JSEXN_ERR, "Expected a type object") +MSG_DEF(JSMSG_TOO_MANY_CON_SPREADARGS, 0, JSEXN_RANGEERR, "too many constructor arguments") +MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 0, JSEXN_RANGEERR, "too many function arguments") +MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGEE, 2, JSEXN_ERR, "{0} is not a debuggee {1}") +MSG_DEF(JSMSG_TYPEDOBJECT_NOT_TYPED_OBJECT, 0, JSEXN_ERR, "Expected a typed object") +MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP,1, JSEXN_TYPEERR, "No such property: {0}") +MSG_DEF(JSMSG_TYPEDOBJECT_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments") +MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 0, JSEXN_TYPEERR, "handle unattached") +MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type") +MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level") +MSG_DEF(JSMSG_NO_IMPORT_NAME, 0, JSEXN_SYNTAXERR, "missing import name") +MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'") +MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name") +MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list") +MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set") +MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword") +MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword") +MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED, 0, JSEXN_SYNTAXERR, "modules are not implemented yet") +MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level") +MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list") +MSG_DEF(JSMSG_NO_EXPORT_NAME, 0, JSEXN_SYNTAXERR, "missing export name") +MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword") +MSG_DEF(JSMSG_INVALID_PROTOTYPE, 0, JSEXN_TYPEERR, "prototype field is not an object") +MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type") +MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}") +MSG_DEF(JSMSG_INVALID_ARG_TYPE, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}") +MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}") +MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP,1, JSEXN_ERR, "No such property on self-hosted object: {0}") +MSG_DEF(JSMSG_PROXY_EXTENSIBILITY, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target") +MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT, 0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object") +MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined") +MSG_DEF(JSMSG_CANT_REPORT_C_AS_NC, 0, JSEXN_TYPEERR, "proxy can't report existing configurable property as non-configurable") +MSG_DEF(JSMSG_COMP_PROP_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing ] in computed property name") \ No newline at end of file diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 89bfa8e876a7..fc2c9b33ad81 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -520,19 +520,6 @@ enum InitState { Uninitialized, Running, ShutDown }; static InitState jsInitState = Uninitialized; #ifdef DEBUG -static void -CheckMessageNumbering() -{ - // Assert that the numbers associated with the error names in js.msg are - // monotonically increasing. It's not a compile-time check, but it's - // better than nothing. - int errorNumber = 0; -# define MSG_DEF(name, number, count, exception, format) \ - JS_ASSERT(name == errorNumber++); -# include "js.msg" -# undef MSG_DEF -} - static unsigned MessageParameterCount(const char *format) { @@ -549,10 +536,8 @@ CheckMessageParameterCounts() { // Assert that each message format has the correct number of braced // parameters. -# define MSG_DEF(name, number, count, exception, format) \ - JS_BEGIN_MACRO \ - JS_ASSERT(MessageParameterCount(format) == count); \ - JS_END_MACRO; +# define MSG_DEF(name, count, exception, format) \ + JS_ASSERT(MessageParameterCount(format) == count); # include "js.msg" # undef MSG_DEF } @@ -570,7 +555,6 @@ JS_Init(void) PRMJ_NowInit(); #ifdef DEBUG - CheckMessageNumbering(); CheckMessageParameterCounts(); #endif diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index eb4cf1c38759..f94beeabba13 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -960,7 +960,7 @@ js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumb } const JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = { -#define MSG_DEF(name, number, count, exception, format) \ +#define MSG_DEF(name, count, exception, format) \ { format, count, exception } , #include "js.msg" #undef MSG_DEF diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 5487e37f6063..fbcdda1d3a0d 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1250,8 +1250,8 @@ js_DateGetMsecSinceEpoch(JSObject *obj); * string and its arguments. */ typedef enum JSErrNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, +#define MSG_DEF(name, count, exception, format) \ + name, #include "js.msg" #undef MSG_DEF JSErr_Limit diff --git a/js/src/jsshell.msg b/js/src/jsshell.msg index 6584a66495dd..1fe53e9e65ed 100644 --- a/js/src/jsshell.msg +++ b/js/src/jsshell.msg @@ -8,22 +8,22 @@ Error messages for JSShell. See js.msg for format. */ -MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") -MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}") -MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr") -MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line") -MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files") -MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}") -MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id") -MSG_DEF(JSSMSG_SCRIPTS_ONLY, 7, 0, JSEXN_NONE, "only works on scripts") -MSG_DEF(JSSMSG_NOT_ENOUGH_ARGS, 8, 1, JSEXN_NONE, "{0}: not enough arguments") -MSG_DEF(JSSMSG_TOO_MANY_ARGS, 9, 1, JSEXN_NONE, "{0}: too many arguments") -MSG_DEF(JSSMSG_ASSERT_EQ_FAILED, 10, 2, JSEXN_NONE, "Assertion failed: got {0}, expected {1}") -MSG_DEF(JSSMSG_ASSERT_EQ_FAILED_MSG, 11, 3, JSEXN_NONE, "Assertion failed: got {0}, expected {1}: {2}") -MSG_DEF(JSSMSG_INVALID_ARGS, 12, 1, JSEXN_NONE, "{0}: invalid arguments") -MSG_DEF(JSSMSG_BAD_ALIGNMENT, 13, 0, JSEXN_NONE, "serialized data must be 8-byte-aligned") -MSG_DEF(JSSMSG_BAD_ENV_VAR, 14, 1, JSEXN_NONE, "unable to read getenv({0})") -MSG_DEF(JSSMSG_NESTED_FAIL, 15, 0, JSEXN_NONE, "error executing nested JS shell") -MSG_DEF(JSSMSG_CACHE_EQ_SIZE_FAILED, 16, 2, JSEXN_NONE, "cache does not have the same size: got {0}, expected {1}") -MSG_DEF(JSSMSG_CACHE_EQ_CONTENT_FAILED, 17, 0, JSEXN_NONE, "cache does not have the same content.") -MSG_DEF(JSSMSG_CACHE_SINGLETON_FAILED, 18, 0, JSEXN_NONE, "compartment cannot save singleton anymore.") +MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, JSEXN_NONE, "") +MSG_DEF(JSSMSG_CANT_OPEN, 2, JSEXN_NONE, "can't open {0}: {1}") +MSG_DEF(JSSMSG_TRAP_USAGE, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr") +MSG_DEF(JSSMSG_LINE2PC_USAGE, 0, JSEXN_NONE, "usage: line2pc [fun] line") +MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 0, JSEXN_NONE, "only works on JS scripts read from files") +MSG_DEF(JSSMSG_UNEXPECTED_EOF, 1, JSEXN_NONE, "unexpected EOF in {0}") +MSG_DEF(JSSMSG_DOEXP_USAGE, 0, JSEXN_NONE, "usage: doexp obj id") +MSG_DEF(JSSMSG_SCRIPTS_ONLY, 0, JSEXN_NONE, "only works on scripts") +MSG_DEF(JSSMSG_NOT_ENOUGH_ARGS, 1, JSEXN_NONE, "{0}: not enough arguments") +MSG_DEF(JSSMSG_TOO_MANY_ARGS, 1, JSEXN_NONE, "{0}: too many arguments") +MSG_DEF(JSSMSG_ASSERT_EQ_FAILED, 2, JSEXN_NONE, "Assertion failed: got {0}, expected {1}") +MSG_DEF(JSSMSG_ASSERT_EQ_FAILED_MSG, 3, JSEXN_NONE, "Assertion failed: got {0}, expected {1}: {2}") +MSG_DEF(JSSMSG_INVALID_ARGS, 1, JSEXN_NONE, "{0}: invalid arguments") +MSG_DEF(JSSMSG_BAD_ALIGNMENT, 0, JSEXN_NONE, "serialized data must be 8-byte-aligned") +MSG_DEF(JSSMSG_BAD_ENV_VAR, 1, JSEXN_NONE, "unable to read getenv({0})") +MSG_DEF(JSSMSG_NESTED_FAIL, 0, JSEXN_NONE, "error executing nested JS shell") +MSG_DEF(JSSMSG_CACHE_EQ_SIZE_FAILED, 2, JSEXN_NONE, "cache does not have the same size: got {0}, expected {1}") +MSG_DEF(JSSMSG_CACHE_EQ_CONTENT_FAILED, 0, JSEXN_NONE, "cache does not have the same content.") +MSG_DEF(JSSMSG_CACHE_SINGLETON_FAILED, 0, JSEXN_NONE, "compartment cannot save singleton anymore.") diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index af2e49cfb2e8..0a56c5b99f69 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -175,8 +175,8 @@ static bool OOM_printAllocationCount = false; #endif enum JSShellErrNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, +#define MSG_DEF(name, count, exception, format) \ + name, #include "jsshell.msg" #undef MSG_DEF JSShellErr_Limit @@ -4902,7 +4902,7 @@ Help(JSContext *cx, unsigned argc, jsval *vp) } static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = { -#define MSG_DEF(name, number, count, exception, format) \ +#define MSG_DEF(name, count, exception, format) \ { format, count, JSEXN_ERR } , #include "jsshell.msg" #undef MSG_DEF From 5dd2bc9938a2544d06cc1cf72a0e59b5302a3468 Mon Sep 17 00:00:00 2001 From: Dan Minor Date: Fri, 15 Aug 2014 08:32:07 -0400 Subject: [PATCH 06/86] Bug 1014653 - Add debug b2g emulator cppunit test failures to manifest; r=gbrown --- testing/b2g_cppunittest_manifest.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/b2g_cppunittest_manifest.txt b/testing/b2g_cppunittest_manifest.txt index c91733baf69e..72a0394deb79 100644 --- a/testing/b2g_cppunittest_manifest.txt +++ b/testing/b2g_cppunittest_manifest.txt @@ -7,3 +7,7 @@ mediapipeline_unittest # Bug 919646 TestStartupCache # Bug 929655 TestStartupCacheTelemetry.manifest # Bug 929655 TestStartupCacheTelemetry.js # Bug 929655 +TestCSPParser # Bug 1054246 +TestDeadlockDetector # Bug 1054249 +test_deadlock_detector # Bug 1054249 +TestTArray # Bug 1054251 From bf4ea5e4eb9374d5d43cc2eaa903fd527d256622 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 15 Aug 2014 09:46:54 -0400 Subject: [PATCH 07/86] Bug 1040735 - DOM node reinsertion under anonymous content may trigger a11y child adoption, r=bz, tbdaunde --- accessible/base/nsAccessibilityService.cpp | 6 +-- accessible/base/nsAccessibilityService.h | 3 +- accessible/generic/Accessible.cpp | 1 - .../tests/mochitest/treeupdate/a11y.ini | 1 + .../mochitest/treeupdate/test_bug1040735.html | 43 +++++++++++++++++++ layout/base/RestyleManager.cpp | 2 +- layout/base/nsCSSFrameConstructor.cpp | 2 +- layout/xul/nsListBoxBodyFrame.cpp | 3 +- 8 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 accessible/tests/mochitest/treeupdate/test_bug1040735.html diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index 520d1b3a7af0..3416f01c452b 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -391,13 +391,13 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell, void nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell, - nsIContent* aContainer, nsIContent* aChild) { + nsIContent* container = aChild->GetFlattenedTreeParent(); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eTree)) { logging::MsgBegin("TREE", "content removed"); - logging::Node("container", aContainer); + logging::Node("container", container); logging::Node("content", aChild); logging::MsgEnd(); logging::Stack(); @@ -406,7 +406,7 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell, DocAccessible* docAccessible = GetDocAccessible(aPresShell); if (docAccessible) - docAccessible->ContentRemoved(aContainer, aChild); + docAccessible->ContentRemoved(container, aChild); } void diff --git a/accessible/base/nsAccessibilityService.h b/accessible/base/nsAccessibilityService.h index da9593713b35..af9bd891b760 100644 --- a/accessible/base/nsAccessibilityService.h +++ b/accessible/base/nsAccessibilityService.h @@ -90,8 +90,7 @@ public: /** * Notification used to update the accessible tree when content is removed. */ - void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer, - nsIContent* aChild); + void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aChild); virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent); diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 4d2f620c6cd8..38a9fd0d1fef 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -2538,7 +2538,6 @@ Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent) if (mParent != aParent) { NS_ERROR("Adopting child!"); mParent->RemoveChild(this); - mParent->InvalidateChildrenGroupInfo(); } else { NS_ERROR("Binding to the same parent!"); return; diff --git a/accessible/tests/mochitest/treeupdate/a11y.ini b/accessible/tests/mochitest/treeupdate/a11y.ini index e3852cd99895..d3f1ffac97db 100644 --- a/accessible/tests/mochitest/treeupdate/a11y.ini +++ b/accessible/tests/mochitest/treeupdate/a11y.ini @@ -5,6 +5,7 @@ [test_bug883708.xhtml] [test_bug884251.xhtml] [test_bug895082.html] +[test_bug1040735.html] [test_canvas.html] [test_colorpicker.xul] [test_contextmenu.xul] diff --git a/accessible/tests/mochitest/treeupdate/test_bug1040735.html b/accessible/tests/mochitest/treeupdate/test_bug1040735.html new file mode 100644 index 000000000000..46d5957fe978 --- /dev/null +++ b/accessible/tests/mochitest/treeupdate/test_bug1040735.html @@ -0,0 +1,43 @@ + + + + Adopt DOM node from anonymous subtree + + + + + + + + + + + + Bug 1040735 +

+ +
+  
+ + + + + + diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 759e06e4a622..da10888cd392 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -3041,7 +3041,7 @@ ElementRestyler::SendAccessibilityNotifications() if (accService) { nsIPresShell* presShell = mFrame->PresContext()->GetPresShell(); nsIContent* content = mFrame->GetContent(); - accService->ContentRemoved(presShell, content->GetParent(), content); + accService->ContentRemoved(presShell, content); // Process children staying shown. uint32_t visibleContentCount = mVisibleKidsOfHiddenElement.Length(); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index d85c39fc7e95..36754831d08a 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7787,7 +7787,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, #ifdef ACCESSIBILITY nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { - accService->ContentRemoved(mPresShell, aContainer, aChild); + accService->ContentRemoved(mPresShell, aChild); } #endif diff --git a/layout/xul/nsListBoxBodyFrame.cpp b/layout/xul/nsListBoxBodyFrame.cpp index 5f4ee0107567..aed33e43ebd7 100644 --- a/layout/xul/nsListBoxBodyFrame.cpp +++ b/layout/xul/nsListBoxBodyFrame.cpp @@ -1470,8 +1470,7 @@ nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState, nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { nsIContent* content = aFrame->GetContent(); - accService->ContentRemoved(PresContext()->PresShell(), content->GetParent(), - content); + accService->ContentRemoved(PresContext()->PresShell(), content); } #endif From 22b7f33edd6c54c9711e9356d3d12d836acf015f Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 15 Aug 2014 10:03:48 -0400 Subject: [PATCH 08/86] Bug 1042469 - Flatten editor/libeditor/base to editor/libeditor; r=poiru --HG-- rename : editor/libeditor/base/ChangeAttributeTxn.cpp => editor/libeditor/ChangeAttributeTxn.cpp rename : editor/libeditor/base/ChangeAttributeTxn.h => editor/libeditor/ChangeAttributeTxn.h rename : editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp => editor/libeditor/ChangeCSSInlineStyleTxn.cpp rename : editor/libeditor/base/ChangeCSSInlineStyleTxn.h => editor/libeditor/ChangeCSSInlineStyleTxn.h rename : editor/libeditor/base/CreateElementTxn.cpp => editor/libeditor/CreateElementTxn.cpp rename : editor/libeditor/base/CreateElementTxn.h => editor/libeditor/CreateElementTxn.h rename : editor/libeditor/base/DeleteNodeTxn.cpp => editor/libeditor/DeleteNodeTxn.cpp rename : editor/libeditor/base/DeleteNodeTxn.h => editor/libeditor/DeleteNodeTxn.h rename : editor/libeditor/base/DeleteRangeTxn.cpp => editor/libeditor/DeleteRangeTxn.cpp rename : editor/libeditor/base/DeleteRangeTxn.h => editor/libeditor/DeleteRangeTxn.h rename : editor/libeditor/base/DeleteTextTxn.cpp => editor/libeditor/DeleteTextTxn.cpp rename : editor/libeditor/base/DeleteTextTxn.h => editor/libeditor/DeleteTextTxn.h rename : editor/libeditor/base/EditActionListener.h => editor/libeditor/EditActionListener.h rename : editor/libeditor/base/EditAggregateTxn.cpp => editor/libeditor/EditAggregateTxn.cpp rename : editor/libeditor/base/EditAggregateTxn.h => editor/libeditor/EditAggregateTxn.h rename : editor/libeditor/base/EditTxn.cpp => editor/libeditor/EditTxn.cpp rename : editor/libeditor/base/EditTxn.h => editor/libeditor/EditTxn.h rename : editor/libeditor/base/IMETextTxn.cpp => editor/libeditor/IMETextTxn.cpp rename : editor/libeditor/base/IMETextTxn.h => editor/libeditor/IMETextTxn.h rename : editor/libeditor/base/InsertElementTxn.cpp => editor/libeditor/InsertElementTxn.cpp rename : editor/libeditor/base/InsertElementTxn.h => editor/libeditor/InsertElementTxn.h rename : editor/libeditor/base/InsertTextTxn.cpp => editor/libeditor/InsertTextTxn.cpp rename : editor/libeditor/base/InsertTextTxn.h => editor/libeditor/InsertTextTxn.h rename : editor/libeditor/base/JoinElementTxn.cpp => editor/libeditor/JoinElementTxn.cpp rename : editor/libeditor/base/JoinElementTxn.h => editor/libeditor/JoinElementTxn.h rename : editor/libeditor/base/PlaceholderTxn.cpp => editor/libeditor/PlaceholderTxn.cpp rename : editor/libeditor/base/PlaceholderTxn.h => editor/libeditor/PlaceholderTxn.h rename : editor/libeditor/base/SetDocTitleTxn.cpp => editor/libeditor/SetDocTitleTxn.cpp rename : editor/libeditor/base/SetDocTitleTxn.h => editor/libeditor/SetDocTitleTxn.h rename : editor/libeditor/base/SplitElementTxn.cpp => editor/libeditor/SplitElementTxn.cpp rename : editor/libeditor/base/SplitElementTxn.h => editor/libeditor/SplitElementTxn.h rename : editor/libeditor/base/crashtests/336104.html => editor/libeditor/crashtests/336104.html rename : editor/libeditor/base/crashtests/382527-1.html => editor/libeditor/crashtests/382527-1.html rename : editor/libeditor/base/crashtests/402172-1.html => editor/libeditor/crashtests/402172-1.html rename : editor/libeditor/base/crashtests/407079-1.html => editor/libeditor/crashtests/407079-1.html rename : editor/libeditor/base/crashtests/407256-1.html => editor/libeditor/crashtests/407256-1.html rename : editor/libeditor/base/crashtests/430624-1.html => editor/libeditor/crashtests/430624-1.html rename : editor/libeditor/base/crashtests/459613-iframe.html => editor/libeditor/crashtests/459613-iframe.html rename : editor/libeditor/base/crashtests/459613.html => editor/libeditor/crashtests/459613.html rename : editor/libeditor/base/crashtests/475132-1.xhtml => editor/libeditor/crashtests/475132-1.xhtml rename : editor/libeditor/base/crashtests/633709.xhtml => editor/libeditor/crashtests/633709.xhtml rename : editor/libeditor/base/crashtests/636074-1.html => editor/libeditor/crashtests/636074-1.html rename : editor/libeditor/base/crashtests/713427-1.html => editor/libeditor/crashtests/713427-1.html rename : editor/libeditor/base/crashtests/713427-2.xhtml => editor/libeditor/crashtests/713427-2.xhtml rename : editor/libeditor/base/crashtests/762183.html => editor/libeditor/crashtests/762183.html rename : editor/libeditor/base/crashtests/766360.html => editor/libeditor/crashtests/766360.html rename : editor/libeditor/base/crashtests/766413.html => editor/libeditor/crashtests/766413.html rename : editor/libeditor/base/crashtests/766845.xhtml => editor/libeditor/crashtests/766845.xhtml rename : editor/libeditor/base/crashtests/768765.html => editor/libeditor/crashtests/768765.html rename : editor/libeditor/base/crashtests/771749.html => editor/libeditor/crashtests/771749.html rename : editor/libeditor/base/crashtests/772282.html => editor/libeditor/crashtests/772282.html rename : editor/libeditor/base/crashtests/776323.html => editor/libeditor/crashtests/776323.html rename : editor/libeditor/base/crashtests/crashtests.list => editor/libeditor/crashtests/crashtests.list rename : editor/libeditor/base/nsEditProperty.h => editor/libeditor/nsEditProperty.h rename : editor/libeditor/base/nsEditPropertyAtomList.h => editor/libeditor/nsEditPropertyAtomList.h rename : editor/libeditor/base/nsEditRules.h => editor/libeditor/nsEditRules.h rename : editor/libeditor/base/nsEditor.cpp => editor/libeditor/nsEditor.cpp rename : editor/libeditor/base/nsEditor.h => editor/libeditor/nsEditor.h rename : editor/libeditor/base/nsEditorCommands.cpp => editor/libeditor/nsEditorCommands.cpp rename : editor/libeditor/base/nsEditorCommands.h => editor/libeditor/nsEditorCommands.h rename : editor/libeditor/base/nsEditorController.cpp => editor/libeditor/nsEditorController.cpp rename : editor/libeditor/base/nsEditorController.h => editor/libeditor/nsEditorController.h rename : editor/libeditor/base/nsEditorEventListener.cpp => editor/libeditor/nsEditorEventListener.cpp rename : editor/libeditor/base/nsEditorEventListener.h => editor/libeditor/nsEditorEventListener.h rename : editor/libeditor/base/nsEditorUtils.cpp => editor/libeditor/nsEditorUtils.cpp rename : editor/libeditor/base/nsEditorUtils.h => editor/libeditor/nsEditorUtils.h rename : editor/libeditor/base/nsIAbsorbingTransaction.h => editor/libeditor/nsIAbsorbingTransaction.h rename : editor/libeditor/base/nsSelectionState.cpp => editor/libeditor/nsSelectionState.cpp rename : editor/libeditor/base/nsSelectionState.h => editor/libeditor/nsSelectionState.h rename : editor/libeditor/base/nsStyleSheetTxns.cpp => editor/libeditor/nsStyleSheetTxns.cpp rename : editor/libeditor/base/nsStyleSheetTxns.h => editor/libeditor/nsStyleSheetTxns.h rename : editor/libeditor/base/tests/chrome.ini => editor/libeditor/tests/chrome.ini rename : editor/libeditor/base/tests/file_bug586662.html => editor/libeditor/tests/file_bug586662.html rename : editor/libeditor/base/tests/mochitest.ini => editor/libeditor/tests/mochitest.ini rename : editor/libeditor/base/tests/moz.build => editor/libeditor/tests/moz.build rename : editor/libeditor/base/tests/test_bug408231.html => editor/libeditor/tests/test_bug408231.html rename : editor/libeditor/base/tests/test_bug46555.html => editor/libeditor/tests/test_bug46555.html rename : editor/libeditor/base/tests/test_bug502673.html => editor/libeditor/tests/test_bug502673.html rename : editor/libeditor/base/tests/test_bug514156.html => editor/libeditor/tests/test_bug514156.html rename : editor/libeditor/base/tests/test_bug567213.html => editor/libeditor/tests/test_bug567213.html rename : editor/libeditor/base/tests/test_bug586662.html => editor/libeditor/tests/test_bug586662.html rename : editor/libeditor/base/tests/test_bug599983.html => editor/libeditor/tests/test_bug599983.html rename : editor/libeditor/base/tests/test_bug599983.xul => editor/libeditor/tests/test_bug599983.xul rename : editor/libeditor/base/tests/test_bug646194.xul => editor/libeditor/tests/test_bug646194.xul rename : editor/libeditor/base/tests/test_bug742261.html => editor/libeditor/tests/test_bug742261.html rename : editor/libeditor/base/tests/test_bug773262.html => editor/libeditor/tests/test_bug773262.html rename : editor/libeditor/base/tests/test_bug795785.html => editor/libeditor/tests/test_bug795785.html rename : editor/libeditor/base/tests/test_composition_event_created_in_chrome.html => editor/libeditor/tests/test_composition_event_created_in_chrome.html rename : editor/libeditor/base/tests/test_dragdrop.html => editor/libeditor/tests/test_dragdrop.html rename : editor/libeditor/base/tests/test_selection_move_commands.xul => editor/libeditor/tests/test_selection_move_commands.xul --- content/html/content/src/moz.build | 2 +- editor/crashtests.list | 2 +- .../{base => }/ChangeAttributeTxn.cpp | 0 .../libeditor/{base => }/ChangeAttributeTxn.h | 0 .../{base => }/ChangeCSSInlineStyleTxn.cpp | 0 .../{base => }/ChangeCSSInlineStyleTxn.h | 0 .../libeditor/{base => }/CreateElementTxn.cpp | 0 .../libeditor/{base => }/CreateElementTxn.h | 0 editor/libeditor/{base => }/DeleteNodeTxn.cpp | 0 editor/libeditor/{base => }/DeleteNodeTxn.h | 0 .../libeditor/{base => }/DeleteRangeTxn.cpp | 0 editor/libeditor/{base => }/DeleteRangeTxn.h | 0 editor/libeditor/{base => }/DeleteTextTxn.cpp | 0 editor/libeditor/{base => }/DeleteTextTxn.h | 0 .../libeditor/{base => }/EditActionListener.h | 0 .../libeditor/{base => }/EditAggregateTxn.cpp | 0 .../libeditor/{base => }/EditAggregateTxn.h | 0 editor/libeditor/{base => }/EditTxn.cpp | 0 editor/libeditor/{base => }/EditTxn.h | 0 editor/libeditor/{base => }/IMETextTxn.cpp | 0 editor/libeditor/{base => }/IMETextTxn.h | 0 .../libeditor/{base => }/InsertElementTxn.cpp | 0 .../libeditor/{base => }/InsertElementTxn.h | 0 editor/libeditor/{base => }/InsertTextTxn.cpp | 0 editor/libeditor/{base => }/InsertTextTxn.h | 0 .../libeditor/{base => }/JoinElementTxn.cpp | 0 editor/libeditor/{base => }/JoinElementTxn.h | 0 .../libeditor/{base => }/PlaceholderTxn.cpp | 0 editor/libeditor/{base => }/PlaceholderTxn.h | 0 .../libeditor/{base => }/SetDocTitleTxn.cpp | 0 editor/libeditor/{base => }/SetDocTitleTxn.h | 0 .../libeditor/{base => }/SplitElementTxn.cpp | 0 editor/libeditor/{base => }/SplitElementTxn.h | 0 editor/libeditor/base/moz.build | 44 ------------------- .../{base => }/crashtests/336104.html | 0 .../{base => }/crashtests/382527-1.html | 0 .../{base => }/crashtests/402172-1.html | 0 .../{base => }/crashtests/407079-1.html | 0 .../{base => }/crashtests/407256-1.html | 0 .../{base => }/crashtests/430624-1.html | 0 .../{base => }/crashtests/459613-iframe.html | 0 .../{base => }/crashtests/459613.html | 0 .../{base => }/crashtests/475132-1.xhtml | 0 .../{base => }/crashtests/633709.xhtml | 0 .../{base => }/crashtests/636074-1.html | 0 .../{base => }/crashtests/713427-1.html | 0 .../{base => }/crashtests/713427-2.xhtml | 0 .../{base => }/crashtests/762183.html | 0 .../{base => }/crashtests/766360.html | 0 .../{base => }/crashtests/766413.html | 0 .../{base => }/crashtests/766845.xhtml | 0 .../{base => }/crashtests/768765.html | 0 .../{base => }/crashtests/771749.html | 0 .../{base => }/crashtests/772282.html | 0 .../{base => }/crashtests/776323.html | 0 .../{base => }/crashtests/crashtests.list | 0 editor/libeditor/html/moz.build | 2 +- editor/libeditor/moz.build | 41 ++++++++++++++++- editor/libeditor/{base => }/nsEditProperty.h | 0 .../{base => }/nsEditPropertyAtomList.h | 0 editor/libeditor/{base => }/nsEditRules.h | 0 editor/libeditor/{base => }/nsEditor.cpp | 0 editor/libeditor/{base => }/nsEditor.h | 0 .../libeditor/{base => }/nsEditorCommands.cpp | 0 .../libeditor/{base => }/nsEditorCommands.h | 0 .../{base => }/nsEditorController.cpp | 0 .../libeditor/{base => }/nsEditorController.h | 0 .../{base => }/nsEditorEventListener.cpp | 0 .../{base => }/nsEditorEventListener.h | 0 editor/libeditor/{base => }/nsEditorUtils.cpp | 0 editor/libeditor/{base => }/nsEditorUtils.h | 0 .../{base => }/nsIAbsorbingTransaction.h | 0 .../libeditor/{base => }/nsSelectionState.cpp | 0 .../libeditor/{base => }/nsSelectionState.h | 0 .../libeditor/{base => }/nsStyleSheetTxns.cpp | 0 .../libeditor/{base => }/nsStyleSheetTxns.h | 0 editor/libeditor/{base => }/tests/chrome.ini | 0 .../{base => }/tests/file_bug586662.html | 0 .../libeditor/{base => }/tests/mochitest.ini | 0 editor/libeditor/{base => }/tests/moz.build | 0 .../{base => }/tests/test_bug408231.html | 0 .../{base => }/tests/test_bug46555.html | 0 .../{base => }/tests/test_bug502673.html | 0 .../{base => }/tests/test_bug514156.html | 0 .../{base => }/tests/test_bug567213.html | 0 .../{base => }/tests/test_bug586662.html | 0 .../{base => }/tests/test_bug599983.html | 0 .../{base => }/tests/test_bug599983.xul | 0 .../{base => }/tests/test_bug646194.xul | 0 .../{base => }/tests/test_bug742261.html | 0 .../{base => }/tests/test_bug773262.html | 0 .../{base => }/tests/test_bug795785.html | 0 ...t_composition_event_created_in_chrome.html | 0 .../{base => }/tests/test_dragdrop.html | 0 .../tests/test_selection_move_commands.xul | 0 editor/libeditor/text/moz.build | 2 +- extensions/spellcheck/hunspell/src/moz.build | 2 +- extensions/spellcheck/src/moz.build | 2 +- layout/build/moz.build | 2 +- layout/forms/moz.build | 2 +- toolkit/content/license.html | 2 +- 101 files changed, 49 insertions(+), 54 deletions(-) rename editor/libeditor/{base => }/ChangeAttributeTxn.cpp (100%) rename editor/libeditor/{base => }/ChangeAttributeTxn.h (100%) rename editor/libeditor/{base => }/ChangeCSSInlineStyleTxn.cpp (100%) rename editor/libeditor/{base => }/ChangeCSSInlineStyleTxn.h (100%) rename editor/libeditor/{base => }/CreateElementTxn.cpp (100%) rename editor/libeditor/{base => }/CreateElementTxn.h (100%) rename editor/libeditor/{base => }/DeleteNodeTxn.cpp (100%) rename editor/libeditor/{base => }/DeleteNodeTxn.h (100%) rename editor/libeditor/{base => }/DeleteRangeTxn.cpp (100%) rename editor/libeditor/{base => }/DeleteRangeTxn.h (100%) rename editor/libeditor/{base => }/DeleteTextTxn.cpp (100%) rename editor/libeditor/{base => }/DeleteTextTxn.h (100%) rename editor/libeditor/{base => }/EditActionListener.h (100%) rename editor/libeditor/{base => }/EditAggregateTxn.cpp (100%) rename editor/libeditor/{base => }/EditAggregateTxn.h (100%) rename editor/libeditor/{base => }/EditTxn.cpp (100%) rename editor/libeditor/{base => }/EditTxn.h (100%) rename editor/libeditor/{base => }/IMETextTxn.cpp (100%) rename editor/libeditor/{base => }/IMETextTxn.h (100%) rename editor/libeditor/{base => }/InsertElementTxn.cpp (100%) rename editor/libeditor/{base => }/InsertElementTxn.h (100%) rename editor/libeditor/{base => }/InsertTextTxn.cpp (100%) rename editor/libeditor/{base => }/InsertTextTxn.h (100%) rename editor/libeditor/{base => }/JoinElementTxn.cpp (100%) rename editor/libeditor/{base => }/JoinElementTxn.h (100%) rename editor/libeditor/{base => }/PlaceholderTxn.cpp (100%) rename editor/libeditor/{base => }/PlaceholderTxn.h (100%) rename editor/libeditor/{base => }/SetDocTitleTxn.cpp (100%) rename editor/libeditor/{base => }/SetDocTitleTxn.h (100%) rename editor/libeditor/{base => }/SplitElementTxn.cpp (100%) rename editor/libeditor/{base => }/SplitElementTxn.h (100%) delete mode 100644 editor/libeditor/base/moz.build rename editor/libeditor/{base => }/crashtests/336104.html (100%) rename editor/libeditor/{base => }/crashtests/382527-1.html (100%) rename editor/libeditor/{base => }/crashtests/402172-1.html (100%) rename editor/libeditor/{base => }/crashtests/407079-1.html (100%) rename editor/libeditor/{base => }/crashtests/407256-1.html (100%) rename editor/libeditor/{base => }/crashtests/430624-1.html (100%) rename editor/libeditor/{base => }/crashtests/459613-iframe.html (100%) rename editor/libeditor/{base => }/crashtests/459613.html (100%) rename editor/libeditor/{base => }/crashtests/475132-1.xhtml (100%) rename editor/libeditor/{base => }/crashtests/633709.xhtml (100%) rename editor/libeditor/{base => }/crashtests/636074-1.html (100%) rename editor/libeditor/{base => }/crashtests/713427-1.html (100%) rename editor/libeditor/{base => }/crashtests/713427-2.xhtml (100%) rename editor/libeditor/{base => }/crashtests/762183.html (100%) rename editor/libeditor/{base => }/crashtests/766360.html (100%) rename editor/libeditor/{base => }/crashtests/766413.html (100%) rename editor/libeditor/{base => }/crashtests/766845.xhtml (100%) rename editor/libeditor/{base => }/crashtests/768765.html (100%) rename editor/libeditor/{base => }/crashtests/771749.html (100%) rename editor/libeditor/{base => }/crashtests/772282.html (100%) rename editor/libeditor/{base => }/crashtests/776323.html (100%) rename editor/libeditor/{base => }/crashtests/crashtests.list (100%) rename editor/libeditor/{base => }/nsEditProperty.h (100%) rename editor/libeditor/{base => }/nsEditPropertyAtomList.h (100%) rename editor/libeditor/{base => }/nsEditRules.h (100%) rename editor/libeditor/{base => }/nsEditor.cpp (100%) rename editor/libeditor/{base => }/nsEditor.h (100%) rename editor/libeditor/{base => }/nsEditorCommands.cpp (100%) rename editor/libeditor/{base => }/nsEditorCommands.h (100%) rename editor/libeditor/{base => }/nsEditorController.cpp (100%) rename editor/libeditor/{base => }/nsEditorController.h (100%) rename editor/libeditor/{base => }/nsEditorEventListener.cpp (100%) rename editor/libeditor/{base => }/nsEditorEventListener.h (100%) rename editor/libeditor/{base => }/nsEditorUtils.cpp (100%) rename editor/libeditor/{base => }/nsEditorUtils.h (100%) rename editor/libeditor/{base => }/nsIAbsorbingTransaction.h (100%) rename editor/libeditor/{base => }/nsSelectionState.cpp (100%) rename editor/libeditor/{base => }/nsSelectionState.h (100%) rename editor/libeditor/{base => }/nsStyleSheetTxns.cpp (100%) rename editor/libeditor/{base => }/nsStyleSheetTxns.h (100%) rename editor/libeditor/{base => }/tests/chrome.ini (100%) rename editor/libeditor/{base => }/tests/file_bug586662.html (100%) rename editor/libeditor/{base => }/tests/mochitest.ini (100%) rename editor/libeditor/{base => }/tests/moz.build (100%) rename editor/libeditor/{base => }/tests/test_bug408231.html (100%) rename editor/libeditor/{base => }/tests/test_bug46555.html (100%) rename editor/libeditor/{base => }/tests/test_bug502673.html (100%) rename editor/libeditor/{base => }/tests/test_bug514156.html (100%) rename editor/libeditor/{base => }/tests/test_bug567213.html (100%) rename editor/libeditor/{base => }/tests/test_bug586662.html (100%) rename editor/libeditor/{base => }/tests/test_bug599983.html (100%) rename editor/libeditor/{base => }/tests/test_bug599983.xul (100%) rename editor/libeditor/{base => }/tests/test_bug646194.xul (100%) rename editor/libeditor/{base => }/tests/test_bug742261.html (100%) rename editor/libeditor/{base => }/tests/test_bug773262.html (100%) rename editor/libeditor/{base => }/tests/test_bug795785.html (100%) rename editor/libeditor/{base => }/tests/test_composition_event_created_in_chrome.html (100%) rename editor/libeditor/{base => }/tests/test_dragdrop.html (100%) rename editor/libeditor/{base => }/tests/test_selection_move_commands.xul (100%) diff --git a/content/html/content/src/moz.build b/content/html/content/src/moz.build index 1e45b0a13e87..9421e0978b89 100644 --- a/content/html/content/src/moz.build +++ b/content/html/content/src/moz.build @@ -178,7 +178,7 @@ LOCAL_INCLUDES += [ '/dom/base', '/dom/canvas', '/dom/xbl', - '/editor/libeditor/base', + '/editor/libeditor', '/editor/libeditor/text', '/editor/txmgr', '/layout/forms', diff --git a/editor/crashtests.list b/editor/crashtests.list index 2b82db4da929..a7459bb00071 100644 --- a/editor/crashtests.list +++ b/editor/crashtests.list @@ -3,7 +3,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. include libeditor/html/crashtests/crashtests.list -include libeditor/base/crashtests/crashtests.list +include libeditor/crashtests/crashtests.list include libeditor/text/crashtests/crashtests.list include composer/crashtests/crashtests.list include txmgr/tests/crashtests/crashtests.list diff --git a/editor/libeditor/base/ChangeAttributeTxn.cpp b/editor/libeditor/ChangeAttributeTxn.cpp similarity index 100% rename from editor/libeditor/base/ChangeAttributeTxn.cpp rename to editor/libeditor/ChangeAttributeTxn.cpp diff --git a/editor/libeditor/base/ChangeAttributeTxn.h b/editor/libeditor/ChangeAttributeTxn.h similarity index 100% rename from editor/libeditor/base/ChangeAttributeTxn.h rename to editor/libeditor/ChangeAttributeTxn.h diff --git a/editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp b/editor/libeditor/ChangeCSSInlineStyleTxn.cpp similarity index 100% rename from editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp rename to editor/libeditor/ChangeCSSInlineStyleTxn.cpp diff --git a/editor/libeditor/base/ChangeCSSInlineStyleTxn.h b/editor/libeditor/ChangeCSSInlineStyleTxn.h similarity index 100% rename from editor/libeditor/base/ChangeCSSInlineStyleTxn.h rename to editor/libeditor/ChangeCSSInlineStyleTxn.h diff --git a/editor/libeditor/base/CreateElementTxn.cpp b/editor/libeditor/CreateElementTxn.cpp similarity index 100% rename from editor/libeditor/base/CreateElementTxn.cpp rename to editor/libeditor/CreateElementTxn.cpp diff --git a/editor/libeditor/base/CreateElementTxn.h b/editor/libeditor/CreateElementTxn.h similarity index 100% rename from editor/libeditor/base/CreateElementTxn.h rename to editor/libeditor/CreateElementTxn.h diff --git a/editor/libeditor/base/DeleteNodeTxn.cpp b/editor/libeditor/DeleteNodeTxn.cpp similarity index 100% rename from editor/libeditor/base/DeleteNodeTxn.cpp rename to editor/libeditor/DeleteNodeTxn.cpp diff --git a/editor/libeditor/base/DeleteNodeTxn.h b/editor/libeditor/DeleteNodeTxn.h similarity index 100% rename from editor/libeditor/base/DeleteNodeTxn.h rename to editor/libeditor/DeleteNodeTxn.h diff --git a/editor/libeditor/base/DeleteRangeTxn.cpp b/editor/libeditor/DeleteRangeTxn.cpp similarity index 100% rename from editor/libeditor/base/DeleteRangeTxn.cpp rename to editor/libeditor/DeleteRangeTxn.cpp diff --git a/editor/libeditor/base/DeleteRangeTxn.h b/editor/libeditor/DeleteRangeTxn.h similarity index 100% rename from editor/libeditor/base/DeleteRangeTxn.h rename to editor/libeditor/DeleteRangeTxn.h diff --git a/editor/libeditor/base/DeleteTextTxn.cpp b/editor/libeditor/DeleteTextTxn.cpp similarity index 100% rename from editor/libeditor/base/DeleteTextTxn.cpp rename to editor/libeditor/DeleteTextTxn.cpp diff --git a/editor/libeditor/base/DeleteTextTxn.h b/editor/libeditor/DeleteTextTxn.h similarity index 100% rename from editor/libeditor/base/DeleteTextTxn.h rename to editor/libeditor/DeleteTextTxn.h diff --git a/editor/libeditor/base/EditActionListener.h b/editor/libeditor/EditActionListener.h similarity index 100% rename from editor/libeditor/base/EditActionListener.h rename to editor/libeditor/EditActionListener.h diff --git a/editor/libeditor/base/EditAggregateTxn.cpp b/editor/libeditor/EditAggregateTxn.cpp similarity index 100% rename from editor/libeditor/base/EditAggregateTxn.cpp rename to editor/libeditor/EditAggregateTxn.cpp diff --git a/editor/libeditor/base/EditAggregateTxn.h b/editor/libeditor/EditAggregateTxn.h similarity index 100% rename from editor/libeditor/base/EditAggregateTxn.h rename to editor/libeditor/EditAggregateTxn.h diff --git a/editor/libeditor/base/EditTxn.cpp b/editor/libeditor/EditTxn.cpp similarity index 100% rename from editor/libeditor/base/EditTxn.cpp rename to editor/libeditor/EditTxn.cpp diff --git a/editor/libeditor/base/EditTxn.h b/editor/libeditor/EditTxn.h similarity index 100% rename from editor/libeditor/base/EditTxn.h rename to editor/libeditor/EditTxn.h diff --git a/editor/libeditor/base/IMETextTxn.cpp b/editor/libeditor/IMETextTxn.cpp similarity index 100% rename from editor/libeditor/base/IMETextTxn.cpp rename to editor/libeditor/IMETextTxn.cpp diff --git a/editor/libeditor/base/IMETextTxn.h b/editor/libeditor/IMETextTxn.h similarity index 100% rename from editor/libeditor/base/IMETextTxn.h rename to editor/libeditor/IMETextTxn.h diff --git a/editor/libeditor/base/InsertElementTxn.cpp b/editor/libeditor/InsertElementTxn.cpp similarity index 100% rename from editor/libeditor/base/InsertElementTxn.cpp rename to editor/libeditor/InsertElementTxn.cpp diff --git a/editor/libeditor/base/InsertElementTxn.h b/editor/libeditor/InsertElementTxn.h similarity index 100% rename from editor/libeditor/base/InsertElementTxn.h rename to editor/libeditor/InsertElementTxn.h diff --git a/editor/libeditor/base/InsertTextTxn.cpp b/editor/libeditor/InsertTextTxn.cpp similarity index 100% rename from editor/libeditor/base/InsertTextTxn.cpp rename to editor/libeditor/InsertTextTxn.cpp diff --git a/editor/libeditor/base/InsertTextTxn.h b/editor/libeditor/InsertTextTxn.h similarity index 100% rename from editor/libeditor/base/InsertTextTxn.h rename to editor/libeditor/InsertTextTxn.h diff --git a/editor/libeditor/base/JoinElementTxn.cpp b/editor/libeditor/JoinElementTxn.cpp similarity index 100% rename from editor/libeditor/base/JoinElementTxn.cpp rename to editor/libeditor/JoinElementTxn.cpp diff --git a/editor/libeditor/base/JoinElementTxn.h b/editor/libeditor/JoinElementTxn.h similarity index 100% rename from editor/libeditor/base/JoinElementTxn.h rename to editor/libeditor/JoinElementTxn.h diff --git a/editor/libeditor/base/PlaceholderTxn.cpp b/editor/libeditor/PlaceholderTxn.cpp similarity index 100% rename from editor/libeditor/base/PlaceholderTxn.cpp rename to editor/libeditor/PlaceholderTxn.cpp diff --git a/editor/libeditor/base/PlaceholderTxn.h b/editor/libeditor/PlaceholderTxn.h similarity index 100% rename from editor/libeditor/base/PlaceholderTxn.h rename to editor/libeditor/PlaceholderTxn.h diff --git a/editor/libeditor/base/SetDocTitleTxn.cpp b/editor/libeditor/SetDocTitleTxn.cpp similarity index 100% rename from editor/libeditor/base/SetDocTitleTxn.cpp rename to editor/libeditor/SetDocTitleTxn.cpp diff --git a/editor/libeditor/base/SetDocTitleTxn.h b/editor/libeditor/SetDocTitleTxn.h similarity index 100% rename from editor/libeditor/base/SetDocTitleTxn.h rename to editor/libeditor/SetDocTitleTxn.h diff --git a/editor/libeditor/base/SplitElementTxn.cpp b/editor/libeditor/SplitElementTxn.cpp similarity index 100% rename from editor/libeditor/base/SplitElementTxn.cpp rename to editor/libeditor/SplitElementTxn.cpp diff --git a/editor/libeditor/base/SplitElementTxn.h b/editor/libeditor/SplitElementTxn.h similarity index 100% rename from editor/libeditor/base/SplitElementTxn.h rename to editor/libeditor/SplitElementTxn.h diff --git a/editor/libeditor/base/moz.build b/editor/libeditor/base/moz.build deleted file mode 100644 index 11c79dbfa57e..000000000000 --- a/editor/libeditor/base/moz.build +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -TEST_DIRS += ['tests'] - -UNIFIED_SOURCES += [ - 'ChangeAttributeTxn.cpp', - 'ChangeCSSInlineStyleTxn.cpp', - 'CreateElementTxn.cpp', - 'DeleteNodeTxn.cpp', - 'DeleteRangeTxn.cpp', - 'DeleteTextTxn.cpp', - 'EditAggregateTxn.cpp', - 'EditTxn.cpp', - 'IMETextTxn.cpp', - 'InsertElementTxn.cpp', - 'InsertTextTxn.cpp', - 'JoinElementTxn.cpp', - 'nsEditor.cpp', - 'nsEditorCommands.cpp', - 'nsEditorController.cpp', - 'nsEditorEventListener.cpp', - 'nsEditorUtils.cpp', - 'nsSelectionState.cpp', - 'nsStyleSheetTxns.cpp', - 'PlaceholderTxn.cpp', - 'SetDocTitleTxn.cpp', - 'SplitElementTxn.cpp', -] - -FAIL_ON_WARNINGS = True - -LOCAL_INCLUDES += [ - '../text', - '/content/base/src', - '/editor/txmgr', - '/extensions/spellcheck/src', - '/layout/style', -] - -FINAL_LIBRARY = 'xul' diff --git a/editor/libeditor/base/crashtests/336104.html b/editor/libeditor/crashtests/336104.html similarity index 100% rename from editor/libeditor/base/crashtests/336104.html rename to editor/libeditor/crashtests/336104.html diff --git a/editor/libeditor/base/crashtests/382527-1.html b/editor/libeditor/crashtests/382527-1.html similarity index 100% rename from editor/libeditor/base/crashtests/382527-1.html rename to editor/libeditor/crashtests/382527-1.html diff --git a/editor/libeditor/base/crashtests/402172-1.html b/editor/libeditor/crashtests/402172-1.html similarity index 100% rename from editor/libeditor/base/crashtests/402172-1.html rename to editor/libeditor/crashtests/402172-1.html diff --git a/editor/libeditor/base/crashtests/407079-1.html b/editor/libeditor/crashtests/407079-1.html similarity index 100% rename from editor/libeditor/base/crashtests/407079-1.html rename to editor/libeditor/crashtests/407079-1.html diff --git a/editor/libeditor/base/crashtests/407256-1.html b/editor/libeditor/crashtests/407256-1.html similarity index 100% rename from editor/libeditor/base/crashtests/407256-1.html rename to editor/libeditor/crashtests/407256-1.html diff --git a/editor/libeditor/base/crashtests/430624-1.html b/editor/libeditor/crashtests/430624-1.html similarity index 100% rename from editor/libeditor/base/crashtests/430624-1.html rename to editor/libeditor/crashtests/430624-1.html diff --git a/editor/libeditor/base/crashtests/459613-iframe.html b/editor/libeditor/crashtests/459613-iframe.html similarity index 100% rename from editor/libeditor/base/crashtests/459613-iframe.html rename to editor/libeditor/crashtests/459613-iframe.html diff --git a/editor/libeditor/base/crashtests/459613.html b/editor/libeditor/crashtests/459613.html similarity index 100% rename from editor/libeditor/base/crashtests/459613.html rename to editor/libeditor/crashtests/459613.html diff --git a/editor/libeditor/base/crashtests/475132-1.xhtml b/editor/libeditor/crashtests/475132-1.xhtml similarity index 100% rename from editor/libeditor/base/crashtests/475132-1.xhtml rename to editor/libeditor/crashtests/475132-1.xhtml diff --git a/editor/libeditor/base/crashtests/633709.xhtml b/editor/libeditor/crashtests/633709.xhtml similarity index 100% rename from editor/libeditor/base/crashtests/633709.xhtml rename to editor/libeditor/crashtests/633709.xhtml diff --git a/editor/libeditor/base/crashtests/636074-1.html b/editor/libeditor/crashtests/636074-1.html similarity index 100% rename from editor/libeditor/base/crashtests/636074-1.html rename to editor/libeditor/crashtests/636074-1.html diff --git a/editor/libeditor/base/crashtests/713427-1.html b/editor/libeditor/crashtests/713427-1.html similarity index 100% rename from editor/libeditor/base/crashtests/713427-1.html rename to editor/libeditor/crashtests/713427-1.html diff --git a/editor/libeditor/base/crashtests/713427-2.xhtml b/editor/libeditor/crashtests/713427-2.xhtml similarity index 100% rename from editor/libeditor/base/crashtests/713427-2.xhtml rename to editor/libeditor/crashtests/713427-2.xhtml diff --git a/editor/libeditor/base/crashtests/762183.html b/editor/libeditor/crashtests/762183.html similarity index 100% rename from editor/libeditor/base/crashtests/762183.html rename to editor/libeditor/crashtests/762183.html diff --git a/editor/libeditor/base/crashtests/766360.html b/editor/libeditor/crashtests/766360.html similarity index 100% rename from editor/libeditor/base/crashtests/766360.html rename to editor/libeditor/crashtests/766360.html diff --git a/editor/libeditor/base/crashtests/766413.html b/editor/libeditor/crashtests/766413.html similarity index 100% rename from editor/libeditor/base/crashtests/766413.html rename to editor/libeditor/crashtests/766413.html diff --git a/editor/libeditor/base/crashtests/766845.xhtml b/editor/libeditor/crashtests/766845.xhtml similarity index 100% rename from editor/libeditor/base/crashtests/766845.xhtml rename to editor/libeditor/crashtests/766845.xhtml diff --git a/editor/libeditor/base/crashtests/768765.html b/editor/libeditor/crashtests/768765.html similarity index 100% rename from editor/libeditor/base/crashtests/768765.html rename to editor/libeditor/crashtests/768765.html diff --git a/editor/libeditor/base/crashtests/771749.html b/editor/libeditor/crashtests/771749.html similarity index 100% rename from editor/libeditor/base/crashtests/771749.html rename to editor/libeditor/crashtests/771749.html diff --git a/editor/libeditor/base/crashtests/772282.html b/editor/libeditor/crashtests/772282.html similarity index 100% rename from editor/libeditor/base/crashtests/772282.html rename to editor/libeditor/crashtests/772282.html diff --git a/editor/libeditor/base/crashtests/776323.html b/editor/libeditor/crashtests/776323.html similarity index 100% rename from editor/libeditor/base/crashtests/776323.html rename to editor/libeditor/crashtests/776323.html diff --git a/editor/libeditor/base/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list similarity index 100% rename from editor/libeditor/base/crashtests/crashtests.list rename to editor/libeditor/crashtests/crashtests.list diff --git a/editor/libeditor/html/moz.build b/editor/libeditor/html/moz.build index 99b4a81030c3..b32b5eff9ba0 100644 --- a/editor/libeditor/html/moz.build +++ b/editor/libeditor/html/moz.build @@ -29,7 +29,7 @@ UNIFIED_SOURCES += [ FAIL_ON_WARNINGS = True LOCAL_INCLUDES += [ - '../base', + '..', '../text', '/content/base/src', '/editor/txmgr', diff --git a/editor/libeditor/moz.build b/editor/libeditor/moz.build index 16c381a80cc7..7cef706aad00 100644 --- a/editor/libeditor/moz.build +++ b/editor/libeditor/moz.build @@ -4,4 +4,43 @@ # 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/. -DIRS += ['base', 'text', 'html'] +DIRS += ['text', 'html'] + +TEST_DIRS += ['tests'] + +UNIFIED_SOURCES += [ + 'ChangeAttributeTxn.cpp', + 'ChangeCSSInlineStyleTxn.cpp', + 'CreateElementTxn.cpp', + 'DeleteNodeTxn.cpp', + 'DeleteRangeTxn.cpp', + 'DeleteTextTxn.cpp', + 'EditAggregateTxn.cpp', + 'EditTxn.cpp', + 'IMETextTxn.cpp', + 'InsertElementTxn.cpp', + 'InsertTextTxn.cpp', + 'JoinElementTxn.cpp', + 'nsEditor.cpp', + 'nsEditorCommands.cpp', + 'nsEditorController.cpp', + 'nsEditorEventListener.cpp', + 'nsEditorUtils.cpp', + 'nsSelectionState.cpp', + 'nsStyleSheetTxns.cpp', + 'PlaceholderTxn.cpp', + 'SetDocTitleTxn.cpp', + 'SplitElementTxn.cpp', +] + +FAIL_ON_WARNINGS = True + +LOCAL_INCLUDES += [ + '/content/base/src', + '/editor/txmgr', + '/extensions/spellcheck/src', + '/layout/style', + 'text', +] + +FINAL_LIBRARY = 'xul' diff --git a/editor/libeditor/base/nsEditProperty.h b/editor/libeditor/nsEditProperty.h similarity index 100% rename from editor/libeditor/base/nsEditProperty.h rename to editor/libeditor/nsEditProperty.h diff --git a/editor/libeditor/base/nsEditPropertyAtomList.h b/editor/libeditor/nsEditPropertyAtomList.h similarity index 100% rename from editor/libeditor/base/nsEditPropertyAtomList.h rename to editor/libeditor/nsEditPropertyAtomList.h diff --git a/editor/libeditor/base/nsEditRules.h b/editor/libeditor/nsEditRules.h similarity index 100% rename from editor/libeditor/base/nsEditRules.h rename to editor/libeditor/nsEditRules.h diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/nsEditor.cpp similarity index 100% rename from editor/libeditor/base/nsEditor.cpp rename to editor/libeditor/nsEditor.cpp diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/nsEditor.h similarity index 100% rename from editor/libeditor/base/nsEditor.h rename to editor/libeditor/nsEditor.h diff --git a/editor/libeditor/base/nsEditorCommands.cpp b/editor/libeditor/nsEditorCommands.cpp similarity index 100% rename from editor/libeditor/base/nsEditorCommands.cpp rename to editor/libeditor/nsEditorCommands.cpp diff --git a/editor/libeditor/base/nsEditorCommands.h b/editor/libeditor/nsEditorCommands.h similarity index 100% rename from editor/libeditor/base/nsEditorCommands.h rename to editor/libeditor/nsEditorCommands.h diff --git a/editor/libeditor/base/nsEditorController.cpp b/editor/libeditor/nsEditorController.cpp similarity index 100% rename from editor/libeditor/base/nsEditorController.cpp rename to editor/libeditor/nsEditorController.cpp diff --git a/editor/libeditor/base/nsEditorController.h b/editor/libeditor/nsEditorController.h similarity index 100% rename from editor/libeditor/base/nsEditorController.h rename to editor/libeditor/nsEditorController.h diff --git a/editor/libeditor/base/nsEditorEventListener.cpp b/editor/libeditor/nsEditorEventListener.cpp similarity index 100% rename from editor/libeditor/base/nsEditorEventListener.cpp rename to editor/libeditor/nsEditorEventListener.cpp diff --git a/editor/libeditor/base/nsEditorEventListener.h b/editor/libeditor/nsEditorEventListener.h similarity index 100% rename from editor/libeditor/base/nsEditorEventListener.h rename to editor/libeditor/nsEditorEventListener.h diff --git a/editor/libeditor/base/nsEditorUtils.cpp b/editor/libeditor/nsEditorUtils.cpp similarity index 100% rename from editor/libeditor/base/nsEditorUtils.cpp rename to editor/libeditor/nsEditorUtils.cpp diff --git a/editor/libeditor/base/nsEditorUtils.h b/editor/libeditor/nsEditorUtils.h similarity index 100% rename from editor/libeditor/base/nsEditorUtils.h rename to editor/libeditor/nsEditorUtils.h diff --git a/editor/libeditor/base/nsIAbsorbingTransaction.h b/editor/libeditor/nsIAbsorbingTransaction.h similarity index 100% rename from editor/libeditor/base/nsIAbsorbingTransaction.h rename to editor/libeditor/nsIAbsorbingTransaction.h diff --git a/editor/libeditor/base/nsSelectionState.cpp b/editor/libeditor/nsSelectionState.cpp similarity index 100% rename from editor/libeditor/base/nsSelectionState.cpp rename to editor/libeditor/nsSelectionState.cpp diff --git a/editor/libeditor/base/nsSelectionState.h b/editor/libeditor/nsSelectionState.h similarity index 100% rename from editor/libeditor/base/nsSelectionState.h rename to editor/libeditor/nsSelectionState.h diff --git a/editor/libeditor/base/nsStyleSheetTxns.cpp b/editor/libeditor/nsStyleSheetTxns.cpp similarity index 100% rename from editor/libeditor/base/nsStyleSheetTxns.cpp rename to editor/libeditor/nsStyleSheetTxns.cpp diff --git a/editor/libeditor/base/nsStyleSheetTxns.h b/editor/libeditor/nsStyleSheetTxns.h similarity index 100% rename from editor/libeditor/base/nsStyleSheetTxns.h rename to editor/libeditor/nsStyleSheetTxns.h diff --git a/editor/libeditor/base/tests/chrome.ini b/editor/libeditor/tests/chrome.ini similarity index 100% rename from editor/libeditor/base/tests/chrome.ini rename to editor/libeditor/tests/chrome.ini diff --git a/editor/libeditor/base/tests/file_bug586662.html b/editor/libeditor/tests/file_bug586662.html similarity index 100% rename from editor/libeditor/base/tests/file_bug586662.html rename to editor/libeditor/tests/file_bug586662.html diff --git a/editor/libeditor/base/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini similarity index 100% rename from editor/libeditor/base/tests/mochitest.ini rename to editor/libeditor/tests/mochitest.ini diff --git a/editor/libeditor/base/tests/moz.build b/editor/libeditor/tests/moz.build similarity index 100% rename from editor/libeditor/base/tests/moz.build rename to editor/libeditor/tests/moz.build diff --git a/editor/libeditor/base/tests/test_bug408231.html b/editor/libeditor/tests/test_bug408231.html similarity index 100% rename from editor/libeditor/base/tests/test_bug408231.html rename to editor/libeditor/tests/test_bug408231.html diff --git a/editor/libeditor/base/tests/test_bug46555.html b/editor/libeditor/tests/test_bug46555.html similarity index 100% rename from editor/libeditor/base/tests/test_bug46555.html rename to editor/libeditor/tests/test_bug46555.html diff --git a/editor/libeditor/base/tests/test_bug502673.html b/editor/libeditor/tests/test_bug502673.html similarity index 100% rename from editor/libeditor/base/tests/test_bug502673.html rename to editor/libeditor/tests/test_bug502673.html diff --git a/editor/libeditor/base/tests/test_bug514156.html b/editor/libeditor/tests/test_bug514156.html similarity index 100% rename from editor/libeditor/base/tests/test_bug514156.html rename to editor/libeditor/tests/test_bug514156.html diff --git a/editor/libeditor/base/tests/test_bug567213.html b/editor/libeditor/tests/test_bug567213.html similarity index 100% rename from editor/libeditor/base/tests/test_bug567213.html rename to editor/libeditor/tests/test_bug567213.html diff --git a/editor/libeditor/base/tests/test_bug586662.html b/editor/libeditor/tests/test_bug586662.html similarity index 100% rename from editor/libeditor/base/tests/test_bug586662.html rename to editor/libeditor/tests/test_bug586662.html diff --git a/editor/libeditor/base/tests/test_bug599983.html b/editor/libeditor/tests/test_bug599983.html similarity index 100% rename from editor/libeditor/base/tests/test_bug599983.html rename to editor/libeditor/tests/test_bug599983.html diff --git a/editor/libeditor/base/tests/test_bug599983.xul b/editor/libeditor/tests/test_bug599983.xul similarity index 100% rename from editor/libeditor/base/tests/test_bug599983.xul rename to editor/libeditor/tests/test_bug599983.xul diff --git a/editor/libeditor/base/tests/test_bug646194.xul b/editor/libeditor/tests/test_bug646194.xul similarity index 100% rename from editor/libeditor/base/tests/test_bug646194.xul rename to editor/libeditor/tests/test_bug646194.xul diff --git a/editor/libeditor/base/tests/test_bug742261.html b/editor/libeditor/tests/test_bug742261.html similarity index 100% rename from editor/libeditor/base/tests/test_bug742261.html rename to editor/libeditor/tests/test_bug742261.html diff --git a/editor/libeditor/base/tests/test_bug773262.html b/editor/libeditor/tests/test_bug773262.html similarity index 100% rename from editor/libeditor/base/tests/test_bug773262.html rename to editor/libeditor/tests/test_bug773262.html diff --git a/editor/libeditor/base/tests/test_bug795785.html b/editor/libeditor/tests/test_bug795785.html similarity index 100% rename from editor/libeditor/base/tests/test_bug795785.html rename to editor/libeditor/tests/test_bug795785.html diff --git a/editor/libeditor/base/tests/test_composition_event_created_in_chrome.html b/editor/libeditor/tests/test_composition_event_created_in_chrome.html similarity index 100% rename from editor/libeditor/base/tests/test_composition_event_created_in_chrome.html rename to editor/libeditor/tests/test_composition_event_created_in_chrome.html diff --git a/editor/libeditor/base/tests/test_dragdrop.html b/editor/libeditor/tests/test_dragdrop.html similarity index 100% rename from editor/libeditor/base/tests/test_dragdrop.html rename to editor/libeditor/tests/test_dragdrop.html diff --git a/editor/libeditor/base/tests/test_selection_move_commands.xul b/editor/libeditor/tests/test_selection_move_commands.xul similarity index 100% rename from editor/libeditor/base/tests/test_selection_move_commands.xul rename to editor/libeditor/tests/test_selection_move_commands.xul diff --git a/editor/libeditor/text/moz.build b/editor/libeditor/text/moz.build index 74531ad9e00e..99eb178d1ae1 100644 --- a/editor/libeditor/text/moz.build +++ b/editor/libeditor/text/moz.build @@ -16,7 +16,7 @@ UNIFIED_SOURCES += [ FAIL_ON_WARNINGS = True LOCAL_INCLUDES += [ - '../base', + '..', '/content/base/src', '/editor/txmgr', ] diff --git a/extensions/spellcheck/hunspell/src/moz.build b/extensions/spellcheck/hunspell/src/moz.build index b0f9595cf086..e2ae33974e07 100644 --- a/extensions/spellcheck/hunspell/src/moz.build +++ b/extensions/spellcheck/hunspell/src/moz.build @@ -35,7 +35,7 @@ FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '/content/base/src', - '/editor/libeditor/base', + '/editor/libeditor', '/extensions/spellcheck/src', ] diff --git a/extensions/spellcheck/src/moz.build b/extensions/spellcheck/src/moz.build index f646250a0acd..bd22d744fe74 100644 --- a/extensions/spellcheck/src/moz.build +++ b/extensions/spellcheck/src/moz.build @@ -21,7 +21,7 @@ FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '../hunspell/src', '/content/base/src', - '/editor/libeditor/base', + '/editor/libeditor', ] EXPORTS.mozilla += [ 'mozSpellChecker.h', diff --git a/layout/build/moz.build b/layout/build/moz.build index b4a4dd4fb933..02b73404fd59 100644 --- a/layout/build/moz.build +++ b/layout/build/moz.build @@ -65,7 +65,7 @@ LOCAL_INCLUDES += [ '/dom/xslt/xpath', '/dom/xslt/xslt', '/editor/composer', - '/editor/libeditor/base', + '/editor/libeditor', '/editor/libeditor/html', '/editor/libeditor/text', '/editor/txmgr', diff --git a/layout/forms/moz.build b/layout/forms/moz.build index 03f61261f2ad..a2130dab62f6 100644 --- a/layout/forms/moz.build +++ b/layout/forms/moz.build @@ -45,7 +45,7 @@ FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '../../content/base/src', '../../content/html/content/src', - '../../editor/libeditor/base', + '../../editor/libeditor', '../../editor/libeditor/text', '../../editor/txmgr', '../base', diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 1331f36cac70..f412f7afd3eb 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -1940,7 +1940,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

This license applies to parts of the code in security/sandbox/, - editor/libeditor/base/nsEditorEventListener.cpp, + editor/libeditor/nsEditorEventListener.cpp, widget/cocoa/GfxInfo.mm and also some files in the directories ipc/chromium/, From 37ef6033e31316a02bd80f3044ad2ded86d44ae8 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Fri, 15 Aug 2014 07:41:33 -0700 Subject: [PATCH 09/86] Bug 1036539 - Add async mode support to GonkNativeWindow r=mikeh,pchang --- dom/camera/GonkCameraHwMgr.cpp | 6 +++- .../media-conduit/WebrtcOMXH264VideoCodec.cpp | 6 +++- .../gonk/nativewindow/GonkBufferQueueJB.cpp | 28 +++++++++++-------- widget/gonk/nativewindow/GonkBufferQueueJB.h | 3 +- .../gonk/nativewindow/GonkBufferQueueKK.cpp | 27 ++++++++++++++---- widget/gonk/nativewindow/GonkBufferQueueKK.h | 13 +++++++++ 6 files changed, 64 insertions(+), 19 deletions(-) diff --git a/dom/camera/GonkCameraHwMgr.cpp b/dom/camera/GonkCameraHwMgr.cpp index e215ee750c38..337b51723ca4 100644 --- a/dom/camera/GonkCameraHwMgr.cpp +++ b/dom/camera/GonkCameraHwMgr.cpp @@ -58,7 +58,7 @@ GonkCameraHardware::OnNewFrame() } RefPtr buffer = mNativeWindow->getCurrentBuffer(); if (!buffer) { - DOM_CAMERA_LOGW("received null frame"); + DOM_CAMERA_LOGE("received null frame"); return; } OnNewPreviewFrame(mTarget, buffer); @@ -185,9 +185,13 @@ GonkCameraHardware::Init() #if ANDROID_VERSION >= 19 mNativeWindow = new GonkNativeWindow(GonkCameraHardware::MIN_UNDEQUEUED_BUFFERS); + sp bq = mNativeWindow->getBufferQueue(); + bq->setSynchronousMode(false); mCamera->setPreviewTarget(mNativeWindow->getBufferQueue()); #elif ANDROID_VERSION >= 17 mNativeWindow = new GonkNativeWindow(GonkCameraHardware::MIN_UNDEQUEUED_BUFFERS); + sp bq = mNativeWindow->getBufferQueue(); + bq->setSynchronousMode(false); mCamera->setPreviewTexture(mNativeWindow->getBufferQueue()); #else mNativeWindow = new GonkNativeWindow(); diff --git a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp index b7fd2b0ad40c..b27737cff903 100644 --- a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp +++ b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp @@ -285,6 +285,7 @@ public: mNativeWindow->setNewFrameCallback(this); // XXX remove buffer changes after a better solution lands - bug 1009420 sp bq = mNativeWindow->getBufferQueue(); + bq->setSynchronousMode(false); // More spare buffers to avoid OMX decoder waiting for native window bq->setMaxAcquiredBufferCount(WEBRTC_OMX_H264_MIN_DECODE_BUFFERS); surface = new Surface(bq); @@ -436,7 +437,10 @@ public: void OnNewFrame() MOZ_OVERRIDE { RefPtr buffer = mNativeWindow->getCurrentBuffer(); - MOZ_ASSERT(buffer != nullptr); + if (!buffer) { + CODEC_LOGE("Decoder NewFrame: Get null buffer"); + return; + } layers::GrallocImage::GrallocData grallocData; grallocData.mPicSize = buffer->GetSize(); diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp index cdf0987cdb7f..0dd25515e286 100755 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp +++ b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp @@ -66,7 +66,7 @@ GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode, mMaxAcquiredBufferCount(1), mDefaultMaxBufferCount(2), mOverrideMaxBufferCount(0), - mSynchronousMode(true), // GonkBufferQueue always works in sync mode. + mSynchronousMode(true), mAllowSynchronousMode(allowSynchronousMode), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), @@ -455,7 +455,19 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp* outFence, } status_t GonkBufferQueue::setSynchronousMode(bool enabled) { - return NO_ERROR; + ST_LOGV("setSynchronousMode: enabled=%d", enabled); + Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!"); + return NO_INIT; + } + + if (mSynchronousMode != enabled) { + mSynchronousMode = enabled; + mDequeueCondition.broadcast(); + } + return OK; } status_t GonkBufferQueue::queueBuffer(int buf, @@ -517,19 +529,10 @@ status_t GonkBufferQueue::queueBuffer(int buf, if (mSynchronousMode) { // In synchronous mode we queue all buffers in a FIFO. mQueue.push_back(buf); - - // Synchronous mode always signals that an additional frame should - // be consumed. - listener = mConsumerListener; } else { // In asynchronous mode we only keep the most recent buffer. if (mQueue.empty()) { mQueue.push_back(buf); - - // Asynchronous mode only signals that a frame should be - // consumed if no previous frame was pending. If a frame were - // pending then the consumer would have already been notified. - listener = mConsumerListener; } else { Fifo::iterator front(mQueue.begin()); // buffer currently queued is freed @@ -538,6 +541,9 @@ status_t GonkBufferQueue::queueBuffer(int buf, *front = buf; } } + // always signals that an additional frame should be consumed + // to handle max acquired buffer count reached case. + listener = mConsumerListener; mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.h b/widget/gonk/nativewindow/GonkBufferQueueJB.h index 11d68127a284..0d8b21ebff67 100755 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.h +++ b/widget/gonk/nativewindow/GonkBufferQueueJB.h @@ -229,7 +229,8 @@ public: // queued buffers will be acquired in order. In asynchronous mode, // a queued buffer may be replaced by a subsequently queued buffer. // - // The default mode is asynchronous. + // The default mode is synchronous. + // This should be called only during initialization. virtual status_t setSynchronousMode(bool enabled); // connect attempts to connect a producer API to the GonkBufferQueue. This diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp index 58b29aa044c2..bb298ec46442 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp +++ b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp @@ -61,7 +61,7 @@ GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode, mMaxAcquiredBufferCount(1), mDefaultMaxBufferCount(2), mOverrideMaxBufferCount(0), -// mSynchronousMode(true), // GonkBufferQueue always works in sync mode. + mSynchronousMode(true), mConsumerControlledByApp(false), mDequeueBufferCannotBlock(false), mUseAsyncBuffer(true), @@ -477,6 +477,22 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp* outFence, bool a return returnFlags; } +status_t GonkBufferQueue::setSynchronousMode(bool enabled) { + ALOGV("setSynchronousMode: enabled=%d", enabled); + Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + ALOGE("setSynchronousMode: BufferQueue has been abandoned!"); + return NO_INIT; + } + + if (mSynchronousMode != enabled) { + mSynchronousMode = enabled; + mDequeueCondition.broadcast(); + } + return OK; +} + status_t GonkBufferQueue::queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output) { ATRACE_CALL(); @@ -586,12 +602,11 @@ status_t GonkBufferQueue::queueBuffer(int buf, // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and // simply queue this buffer. mQueue.push_back(item); - listener = mConsumerListener; } else { // when the queue is not empty, we need to look at the front buffer // state and see if we need to replace it. Fifo::iterator front(mQueue.begin()); - if (front->mIsDroppable) { + if (front->mIsDroppable || !mSynchronousMode) { // buffer slot currently queued is marked free if still tracked if (stillTracking(front)) { mSlots[front->mBuf].mBufferState = BufferSlot::FREE; @@ -603,9 +618,11 @@ status_t GonkBufferQueue::queueBuffer(int buf, *front = item; } else { mQueue.push_back(item); - listener = mConsumerListener; } } + // always signals that an additional frame should be consumed + // to handle max acquired buffer count reached case. + listener = mConsumerListener; mBufferHasBeenQueued = true; mDequeueCondition.broadcast(); @@ -1171,7 +1188,7 @@ int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const { // we're in async mode, or we want to prevent the app to // deadlock itself, we throw-in an extra buffer to guarantee it. - if (mDequeueBufferCannotBlock || async) + if (mDequeueBufferCannotBlock || async || !mSynchronousMode) return mMaxAcquiredBufferCount + 1; return mMaxAcquiredBufferCount; diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.h b/widget/gonk/nativewindow/GonkBufferQueueKK.h index 2e515d35d289..27d1fdc4bca0 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.h +++ b/widget/gonk/nativewindow/GonkBufferQueueKK.h @@ -187,6 +187,16 @@ public: // will usually be the one obtained from dequeueBuffer. virtual void cancelBuffer(int buf, const sp& fence); + // setSynchronousMode sets whether dequeueBuffer is synchronous or + // asynchronous. In synchronous mode, dequeueBuffer blocks until + // a buffer is available, the currently bound buffer can be dequeued and + // queued buffers will be acquired in order. In asynchronous mode, + // a queued buffer may be replaced by a subsequently queued buffer. + // + // The default mode is synchronous. + // This should be called only during initialization. + virtual status_t setSynchronousMode(bool enabled); + // connect attempts to connect a producer API to the GonkBufferQueue. This // must be called before any other IGraphicBufferProducer methods are // called except for getAllocator. A consumer must already be connected. @@ -499,6 +509,9 @@ private: // to NULL and is written by consumerConnect and consumerDisconnect. sp mConsumerListener; + // mSynchronousMode whether we're in synchronous mode or not + bool mSynchronousMode; + // mConsumerControlledByApp whether the connected consumer is controlled by the // application. bool mConsumerControlledByApp; From 1e9808ffe1d212e626f2b855d87317a47732a7a3 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Fri, 15 Aug 2014 23:52:46 +0900 Subject: [PATCH 10/86] Bug 1054108 nsTextStore::GetTextExt() should return the position of composition start if the layout hasn't been computed yet and when Free ChangJie or Easy Changjei is active TIP r=emk --- modules/libpref/init/all.js | 7 ++++++ widget/windows/nsTextStore.cpp | 46 +++++++++++++++++++++++++++++++--- widget/windows/nsTextStore.h | 2 ++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 63fa2bd2c26a..12dedaa261e2 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2824,6 +2824,13 @@ pref("intl.tsf.support_imm", true); // Whether creates native caret for ATOK or not. pref("intl.tsf.hack.atok.create_native_caret", true); +// Whether use composition start position for the result of +// ITfContextView::GetTextExt() if the specified range is larger than +// composition start offset. +// For Free ChangJie 2010 +pref("intl.tsf.hack.free_chang_jie.do_not_return_no_layout_error", true); +// For Easy Changjei +pref("intl.tsf.hack.easy_changjei.do_not_return_no_layout_error", true); #endif // See bug 448927, on topmost panel, some IMEs are not usable on Windows. diff --git a/widget/windows/nsTextStore.cpp b/widget/windows/nsTextStore.cpp index c5fd60e4d0d5..75886d495a53 100644 --- a/widget/windows/nsTextStore.cpp +++ b/widget/windows/nsTextStore.cpp @@ -135,6 +135,17 @@ DWORD nsTextStore::sTsfClientId = 0; nsTextStore* nsTextStore::sTsfTextStore = nullptr; bool nsTextStore::sCreateNativeCaretForATOK = false; +bool nsTextStore::sDoNotReturnNoLayoutErrorToFreeChangJie = false; +bool nsTextStore::sDoNotReturnNoLayoutErrorToEasyChangjei = false; + +#define TIP_NAME_BEGINS_WITH_ATOK \ + (NS_LITERAL_STRING("ATOK ")) +// NOTE: Free ChangJie 2010 missspells its name... +#define TIP_NAME_FREE_CHANG_JIE_2010 \ + (NS_LITERAL_STRING("Free CangJie IME 10")) +#define TIP_NAME_EASY_CHANGJEI \ + (NS_LITERAL_STRING( \ + "\x4E2D\x6587 (\x7E41\x9AD4) - \x6613\x9821\x8F38\x5165\x6CD5")) UINT nsTextStore::sFlushTIPInputMessage = 0; @@ -2550,6 +2561,25 @@ nsTextStore::GetTextExt(TsViewCookie vcView, return TS_E_INVALIDPOS; } + // Free ChangJie 2010 and Easy Changjei 1.0.12.0 doesn't handle + // ITfContextView::GetTextExt() properly. Prehaps, it's due to a bug of TSF. + // TSF (at least on Win 8.1) doesn't return TS_E_NOLAYOUT to the caller + // even if we return it. It's converted to just E_FAIL. + // TODO: On Win 9, we need to check this hack is still necessary. + if ((sDoNotReturnNoLayoutErrorToFreeChangJie && + mActiveTIPKeyboardDescription.Equals(TIP_NAME_FREE_CHANG_JIE_2010)) || + (sDoNotReturnNoLayoutErrorToEasyChangjei && + mActiveTIPKeyboardDescription.Equals(TIP_NAME_EASY_CHANGJEI)) && + mComposition.IsComposing() && + mContent.IsLayoutChangedAfter(acpEnd) && + mComposition.mStart < acpEnd) { + acpEnd = mComposition.mStart; + acpStart = std::min(acpStart, acpEnd); + PR_LOG(sTextStoreLog, PR_LOG_DEBUG, + ("TSF: 0x%p nsTextStore::GetTextExt() hacked the offsets for TIP " + "acpStart=%d, acpEnd=%d", this, acpStart, acpEnd)); + } + if (mContent.IsLayoutChangedAfter(acpEnd)) { PR_LOG(sTextStoreLog, PR_LOG_ERROR, ("TSF: 0x%p nsTextStore::GetTextExt() FAILED due to " @@ -2615,7 +2645,7 @@ nsTextStore::GetTextExt(TsViewCookie vcView, // for hacking the bug. if (sCreateNativeCaretForATOK && StringBeginsWith( - mActiveTIPKeyboardDescription, NS_LITERAL_STRING("ATOK ")) && + mActiveTIPKeyboardDescription, TIP_NAME_BEGINS_WITH_ATOK) && mComposition.IsComposing() && mComposition.mStart <= acpStart && mComposition.EndOffset() >= acpStart && mComposition.mStart <= acpEnd && mComposition.EndOffset() >= acpEnd) { @@ -4034,6 +4064,12 @@ nsTextStore::Initialize() sCreateNativeCaretForATOK = Preferences::GetBool("intl.tsf.hack.atok.create_native_caret", true); + sDoNotReturnNoLayoutErrorToFreeChangJie = + Preferences::GetBool( + "intl.tsf.hack.free_chang_jie.do_not_return_no_layout_error", true); + sDoNotReturnNoLayoutErrorToEasyChangjei = + Preferences::GetBool( + "intl.tsf.hack.easy_changjei.do_not_return_no_layout_error", true); MOZ_ASSERT(!sFlushTIPInputMessage); sFlushTIPInputMessage = ::RegisterWindowMessageW(L"Flush TIP Input Message"); @@ -4042,10 +4078,14 @@ nsTextStore::Initialize() ("TSF: nsTextStore::Initialize(), sTsfThreadMgr=0x%p, " "sTsfClientId=0x%08X, sTsfTextStore=0x%p, sDisplayAttrMgr=0x%p, " "sCategoryMgr=0x%p, sTsfDisabledDocumentMgr=0x%p, sTsfDisabledContext=%p, " - "sCreateNativeCaretForATOK=%s", + "sCreateNativeCaretForATOK=%s, " + "sDoNotReturnNoLayoutErrorToFreeChangJie=%s, " + "sDoNotReturnNoLayoutErrorToEasyChangjei=%s", sTsfThreadMgr, sTsfClientId, sTsfTextStore, sDisplayAttrMgr, sCategoryMgr, sTsfDisabledDocumentMgr, sTsfDisabledContext, - GetBoolName(sCreateNativeCaretForATOK))); + GetBoolName(sCreateNativeCaretForATOK), + GetBoolName(sDoNotReturnNoLayoutErrorToFreeChangJie), + GetBoolName(sDoNotReturnNoLayoutErrorToEasyChangjei))); } // static diff --git a/widget/windows/nsTextStore.h b/widget/windows/nsTextStore.h index e347d805b393..6ce75996c347 100644 --- a/widget/windows/nsTextStore.h +++ b/widget/windows/nsTextStore.h @@ -739,6 +739,8 @@ protected: // Enables/Disables hack for specific TIP. static bool sCreateNativeCaretForATOK; + static bool sDoNotReturnNoLayoutErrorToFreeChangJie; + static bool sDoNotReturnNoLayoutErrorToEasyChangjei; // Message the Tablet Input Panel uses to flush text during blurring. // See comments in Destroy From b0b695d91c68651835949996234958ed67deb8ea Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Fri, 15 Aug 2014 10:55:48 -0400 Subject: [PATCH 11/86] Bug 1054114 - Add exception stacks logged in test_status to mach and tbpl formatters.;r=jgraham --- .../mozlog/mozlog/structured/formatters/machformatter.py | 8 +++++++- .../mozlog/mozlog/structured/formatters/tbplformatter.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py b/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py index a0d5ea7e22df..5536e3a1b738 100644 --- a/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py +++ b/testing/mozbase/mozlog/mozlog/structured/formatters/machformatter.py @@ -215,11 +215,17 @@ class MachFormatter(base.BaseFormatter): self.status_buffer[test] = {"count": 0, "unexpected": [], "pass": 0} self.status_buffer[test]["count"] += 1 + message = data.get("message", "") + if "stack" in data: + if message: + message += "\n" + message += data["stack"] + if "expected" in data: self.status_buffer[test]["unexpected"].append((data["subtest"], data["status"], data["expected"], - data.get("message", ""))) + message)) if data["status"] == "PASS": self.status_buffer[test]["pass"] += 1 diff --git a/testing/mozbase/mozlog/mozlog/structured/formatters/tbplformatter.py b/testing/mozbase/mozlog/mozlog/structured/formatters/tbplformatter.py index 80027db9fd31..eb13f9f63509 100644 --- a/testing/mozbase/mozlog/mozlog/structured/formatters/tbplformatter.py +++ b/testing/mozbase/mozlog/mozlog/structured/formatters/tbplformatter.py @@ -41,6 +41,8 @@ class TbplFormatter(BaseFormatter): def test_status(self, data): message = "- " + data["message"] if "message" in data else "" + if "stack" in data: + message += "\n%s" % data["stack"] if "expected" in data: failure_line = "TEST-UNEXPECTED-%s | %s | %s %s" % ( data["status"], self.id_str(data["test"]), data["subtest"], From 2d848a096c6fcff8d1ba4832f9ccd17801a01d94 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Fri, 15 Aug 2014 16:03:03 +0100 Subject: [PATCH 12/86] Backed out changeset 8589d9bdd501 (bug 1040735) for B2G gaia-ui-test crashes --- accessible/base/nsAccessibilityService.cpp | 6 +-- accessible/base/nsAccessibilityService.h | 3 +- accessible/generic/Accessible.cpp | 1 + .../tests/mochitest/treeupdate/a11y.ini | 1 - .../mochitest/treeupdate/test_bug1040735.html | 43 ------------------- layout/base/RestyleManager.cpp | 2 +- layout/base/nsCSSFrameConstructor.cpp | 2 +- layout/xul/nsListBoxBodyFrame.cpp | 3 +- 8 files changed, 10 insertions(+), 51 deletions(-) delete mode 100644 accessible/tests/mochitest/treeupdate/test_bug1040735.html diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index 3416f01c452b..520d1b3a7af0 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -391,13 +391,13 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell, void nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell, + nsIContent* aContainer, nsIContent* aChild) { - nsIContent* container = aChild->GetFlattenedTreeParent(); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eTree)) { logging::MsgBegin("TREE", "content removed"); - logging::Node("container", container); + logging::Node("container", aContainer); logging::Node("content", aChild); logging::MsgEnd(); logging::Stack(); @@ -406,7 +406,7 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell, DocAccessible* docAccessible = GetDocAccessible(aPresShell); if (docAccessible) - docAccessible->ContentRemoved(container, aChild); + docAccessible->ContentRemoved(aContainer, aChild); } void diff --git a/accessible/base/nsAccessibilityService.h b/accessible/base/nsAccessibilityService.h index af9bd891b760..da9593713b35 100644 --- a/accessible/base/nsAccessibilityService.h +++ b/accessible/base/nsAccessibilityService.h @@ -90,7 +90,8 @@ public: /** * Notification used to update the accessible tree when content is removed. */ - void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aChild); + void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer, + nsIContent* aChild); virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent); diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 38a9fd0d1fef..4d2f620c6cd8 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -2538,6 +2538,7 @@ Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent) if (mParent != aParent) { NS_ERROR("Adopting child!"); mParent->RemoveChild(this); + mParent->InvalidateChildrenGroupInfo(); } else { NS_ERROR("Binding to the same parent!"); return; diff --git a/accessible/tests/mochitest/treeupdate/a11y.ini b/accessible/tests/mochitest/treeupdate/a11y.ini index d3f1ffac97db..e3852cd99895 100644 --- a/accessible/tests/mochitest/treeupdate/a11y.ini +++ b/accessible/tests/mochitest/treeupdate/a11y.ini @@ -5,7 +5,6 @@ [test_bug883708.xhtml] [test_bug884251.xhtml] [test_bug895082.html] -[test_bug1040735.html] [test_canvas.html] [test_colorpicker.xul] [test_contextmenu.xul] diff --git a/accessible/tests/mochitest/treeupdate/test_bug1040735.html b/accessible/tests/mochitest/treeupdate/test_bug1040735.html deleted file mode 100644 index 46d5957fe978..000000000000 --- a/accessible/tests/mochitest/treeupdate/test_bug1040735.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - Adopt DOM node from anonymous subtree - - - - - - - - - - - - Bug 1040735 -

- -
-  
- - - - - - diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index da10888cd392..759e06e4a622 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -3041,7 +3041,7 @@ ElementRestyler::SendAccessibilityNotifications() if (accService) { nsIPresShell* presShell = mFrame->PresContext()->GetPresShell(); nsIContent* content = mFrame->GetContent(); - accService->ContentRemoved(presShell, content); + accService->ContentRemoved(presShell, content->GetParent(), content); // Process children staying shown. uint32_t visibleContentCount = mVisibleKidsOfHiddenElement.Length(); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 36754831d08a..d85c39fc7e95 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7787,7 +7787,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, #ifdef ACCESSIBILITY nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { - accService->ContentRemoved(mPresShell, aChild); + accService->ContentRemoved(mPresShell, aContainer, aChild); } #endif diff --git a/layout/xul/nsListBoxBodyFrame.cpp b/layout/xul/nsListBoxBodyFrame.cpp index aed33e43ebd7..5f4ee0107567 100644 --- a/layout/xul/nsListBoxBodyFrame.cpp +++ b/layout/xul/nsListBoxBodyFrame.cpp @@ -1470,7 +1470,8 @@ nsListBoxBodyFrame::RemoveChildFrame(nsBoxLayoutState &aState, nsAccessibilityService* accService = nsIPresShell::AccService(); if (accService) { nsIContent* content = aFrame->GetContent(); - accService->ContentRemoved(PresContext()->PresShell(), content); + accService->ContentRemoved(PresContext()->PresShell(), content->GetParent(), + content); } #endif From 5559ec0293503b502af1eb51c4e44aa1c5c6109a Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Fri, 15 Aug 2014 16:14:42 +0100 Subject: [PATCH 13/86] Backed out changeset f4b101378a07 (bug 1021527) by request --- b2g/installer/package-manifest.in | 18 ++++- editor/composer/moz.build | 18 ++++- editor/composer/res/caret_left.svg | 24 ------- editor/composer/res/caret_middle.svg | 24 ------- editor/composer/res/caret_right.svg | 24 ------- layout/style/ua.css | 98 ++++++++++++++++++++++++---- 6 files changed, 117 insertions(+), 89 deletions(-) delete mode 100644 editor/composer/res/caret_left.svg delete mode 100644 editor/composer/res/caret_middle.svg delete mode 100644 editor/composer/res/caret_right.svg diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 764bdbd73f9f..8d06eb11789b 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -657,9 +657,6 @@ ; [Layout Engine Resources] ; Style Sheets, Graphics and other Resources used by the layout engine. @BINPATH@/res/EditorOverride.css -@BINPATH@/res/caret_left.svg -@BINPATH@/res/caret_middle.svg -@BINPATH@/res/caret_right.svg @BINPATH@/res/contenteditable.css @BINPATH@/res/designmode.css @BINPATH@/res/ImageDocument.css @@ -683,6 +680,21 @@ @BINPATH@/res/table-remove-row-active.gif @BINPATH@/res/table-remove-row-hover.gif @BINPATH@/res/table-remove-row.gif +@BINPATH@/res/text_caret.png +@BINPATH@/res/text_caret@1.5x.png +@BINPATH@/res/text_caret@2.25x.png +@BINPATH@/res/text_caret@2x.png +@BINPATH@/res/text_caret_tilt_left.png +@BINPATH@/res/text_caret_tilt_left@1.5x.png +@BINPATH@/res/text_caret_tilt_left@2.25x.png +@BINPATH@/res/text_caret_tilt_left@2x.png +@BINPATH@/res/text_caret_tilt_right.png +@BINPATH@/res/text_caret_tilt_right@1.5x.png +@BINPATH@/res/text_caret_tilt_right@2.25x.png +@BINPATH@/res/text_caret_tilt_right@2x.png +@BINPATH@/res/text_selection_handle.png +@BINPATH@/res/text_selection_handle@1.5.png +@BINPATH@/res/text_selection_handle@2.png @BINPATH@/res/grabber.gif #ifdef XP_MACOSX @BINPATH@/res/cursors/* diff --git a/editor/composer/moz.build b/editor/composer/moz.build index e7ae6a3b9176..20d33b0af424 100644 --- a/editor/composer/moz.build +++ b/editor/composer/moz.build @@ -27,9 +27,6 @@ FAIL_ON_WARNINGS = True FINAL_LIBRARY = 'xul' RESOURCE_FILES += [ - 'res/caret_left.svg', - 'res/caret_middle.svg', - 'res/caret_right.svg', 'res/EditorOverride.css', 'res/grabber.gif', 'res/table-add-column-after-active.gif', @@ -50,4 +47,19 @@ RESOURCE_FILES += [ 'res/table-remove-row-active.gif', 'res/table-remove-row-hover.gif', 'res/table-remove-row.gif', + 'res/text_caret.png', + 'res/text_caret@1.5x.png', + 'res/text_caret@2.25x.png', + 'res/text_caret@2x.png', + 'res/text_caret_tilt_left.png', + 'res/text_caret_tilt_left@1.5x.png', + 'res/text_caret_tilt_left@2.25x.png', + 'res/text_caret_tilt_left@2x.png', + 'res/text_caret_tilt_right.png', + 'res/text_caret_tilt_right@1.5x.png', + 'res/text_caret_tilt_right@2.25x.png', + 'res/text_caret_tilt_right@2x.png', + 'res/text_selection_handle.png', + 'res/text_selection_handle@1.5.png', + 'res/text_selection_handle@2.png', ] diff --git a/editor/composer/res/caret_left.svg b/editor/composer/res/caret_left.svg deleted file mode 100644 index 24b7baa3124a..000000000000 --- a/editor/composer/res/caret_left.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - diff --git a/editor/composer/res/caret_middle.svg b/editor/composer/res/caret_middle.svg deleted file mode 100644 index c50361f1a845..000000000000 --- a/editor/composer/res/caret_middle.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - diff --git a/editor/composer/res/caret_right.svg b/editor/composer/res/caret_right.svg deleted file mode 100644 index 6b0b6ccf758d..000000000000 --- a/editor/composer/res/caret_right.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - diff --git a/layout/style/ua.css b/layout/style/ua.css index 87811f0c1cbd..f19892ca7544 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -53,7 +53,7 @@ display: table-row !important; } -/* The ::-moz-table-column pseudo-element is for extra columns at the end +/* The ::-moz-table-column pseudo-element is for extra columns at the end of a table. */ *|*::-moz-table-column { display: table-column !important; @@ -62,7 +62,7 @@ *|*::-moz-table-column-group { display: table-column-group !important; } - + *|*::-moz-table-row-group { display: table-row-group !important; } @@ -186,7 +186,7 @@ %endif } -*|*::-moz-column-content { +*|*::-moz-column-content { /* the column boxes inside a column-flowed block */ /* make unicode-bidi inherit, otherwise it has no effect on column boxes */ unicode-bidi: inherit; @@ -307,27 +307,103 @@ parsererror|sourcetext { font-size: 12pt; } -div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret, +div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret { + background-image: url("resource://gre/res/text_selection_handle.png"); + position: absolute; + width: 19px; + height: 24px; + margin-left: -10px; + background-position: center center; + z-index: 2147483647; +} + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left, div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right { - background-image: url("resource://gre/res/caret_middle.svg"); + background-image: url("resource://gre/res/text_caret.png"); position: absolute; - width: 29px; - height: 31px; - margin-left: -15px; + width: 21px; + height: 26px; + margin-left: -11px; background-position: center center; background-size: 100% 100%; z-index: 2147483647; } div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left.tilt { - background-image: url("resource://gre/res/caret_left.svg"); - margin-left: -29px; + background-image: url("resource://gre/res/text_caret_tilt_left.png"); + margin-left: -22px; + width: 22px; } div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right.tilt { - background-image: url("resource://gre/res/caret_right.svg"); + background-image: url("resource://gre/res/text_caret_tilt_right.png"); margin-left: 0px; + width: 22px; +} + +@media (min-resolution: 1.5dppx) { + div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret { + background-image: url("resource://gre/res/text_selection_handle@1.5.png"); + position: absolute; + width: 29px; + height: 36px; + margin-left: -15px; + background-position: center center; + z-index: 2147483647; + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left, + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right { + background-image: url("resource://gre/res/text_caret@1.5x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left.tilt { + background-image: url("resource://gre/res/text_caret_tilt_left@1.5x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right.tilt { + background-image: url("resource://gre/res/text_caret_tilt_right@1.5x.png"); + } +} + +@media (min-resolution: 2dppx) { + div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret { + background-image: url("resource://gre/res/text_selection_handle@2.png"); + position: absolute; + width: 38px; + height: 48px; + margin-left: -19px; + background-position: center center; + z-index: 2147483647; + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left, + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right { + background-image: url("resource://gre/res/text_caret@2x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left.tilt { + background-image: url("resource://gre/res/text_caret_tilt_left@2x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right.tilt { + background-image: url("resource://gre/res/text_caret_tilt_right@2x.png"); + } +} + +@media (min-resolution: 2.25dppx) { + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right { + background-image: url("resource://gre/res/text_caret@2.25x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-left.tilt { + background-image: url("resource://gre/res/text_caret_tilt_left@2.25x.png"); + } + + div[\_moz_anonclass="mozTouchCaret"].moz-selectioncaret-right.tilt { + background-image: url("resource://gre/res/text_caret_tilt_right@2.25x.png"); + } } div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret.hidden, From 5b25273c1bc24822d138a8dc5475ab8da2939a7d Mon Sep 17 00:00:00 2001 From: Artem Sobolev Date: Tue, 29 Jul 2014 15:23:22 -0700 Subject: [PATCH 14/86] Bug 625012 - Handle multipart responses in ImageDocument::OnStartRequest correctly. r=bz --- content/html/document/src/ImageDocument.cpp | 18 ++++++----- content/html/document/src/MediaDocument.cpp | 12 ++++++-- docshell/base/nsDSURIContentListener.cpp | 33 +++++++++++++++++++-- docshell/base/nsDSURIContentListener.h | 5 ++++ image/src/imgRequest.cpp | 2 ++ 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/content/html/document/src/ImageDocument.cpp b/content/html/document/src/ImageDocument.cpp index c85a85b31fd4..97ec8415be3d 100644 --- a/content/html/document/src/ImageDocument.cpp +++ b/content/html/document/src/ImageDocument.cpp @@ -113,12 +113,14 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) return NS_OK; } - nsCOMPtr imageLoader = do_QueryInterface(imgDoc->mImageContent); - NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED); + if (!imgDoc->mObservingImageLoader) { + nsCOMPtr imageLoader = do_QueryInterface(imgDoc->mImageContent); + NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED); - imageLoader->AddObserver(imgDoc); - imgDoc->mObservingImageLoader = true; - imageLoader->LoadImageWithChannel(channel, getter_AddRefs(mNextStream)); + imageLoader->AddObserver(imgDoc); + imgDoc->mObservingImageLoader = true; + imageLoader->LoadImageWithChannel(channel, getter_AddRefs(mNextStream)); + } return MediaDocumentStreamListener::OnStartRequest(request, ctxt); } @@ -384,12 +386,14 @@ ImageDocument::ScrollImageTo(int32_t aX, int32_t aY, bool restoreImage) } nsCOMPtr shell = GetShell(); - if (!shell) + if (!shell) { return; + } nsIScrollableFrame* sf = shell->GetRootScrollFrameAsScrollable(); - if (!sf) + if (!sf) { return; + } nsRect portRect = sf->GetScrollPortRect(); sf->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aX/ratio) - portRect.width/2, diff --git a/content/html/document/src/MediaDocument.cpp b/content/html/document/src/MediaDocument.cpp index 10be92e03de2..22bce9c60a8f 100644 --- a/content/html/document/src/MediaDocument.cpp +++ b/content/html/document/src/MediaDocument.cpp @@ -21,6 +21,7 @@ #include "mozilla/Services.h" #include "nsServiceManagerUtils.h" #include "nsIPrincipal.h" +#include "nsIMultiPartChannel.h" namespace mozilla { namespace dom { @@ -70,9 +71,16 @@ MediaDocumentStreamListener::OnStopRequest(nsIRequest* request, rv = mNextStream->OnStopRequest(request, ctxt, status); } - // No more need for our document so clear our reference and prevent leaks - mDocument = nullptr; + // Don't release mDocument here if we're in the middle of a multipart response. + bool lastPart = true; + nsCOMPtr mpchan(do_QueryInterface(request)); + if (mpchan) { + mpchan->GetIsLastPart(&lastPart); + } + if (lastPart) { + mDocument = nullptr; + } return rv; } diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp index 10e3564bdd59..5e6b1e826588 100644 --- a/docshell/base/nsDSURIContentListener.cpp +++ b/docshell/base/nsDSURIContentListener.cpp @@ -20,6 +20,7 @@ #include "nsIConsoleService.h" #include "nsIScriptError.h" #include "nsDocShellLoadTypes.h" +#include "nsIMultiPartChannel.h" using namespace mozilla; @@ -28,8 +29,9 @@ using namespace mozilla; //***************************************************************************** nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell) - : mDocShell(aDocShell), - mParentContentListener(nullptr) + : mDocShell(aDocShell) + , mExistingJPEGRequest(nullptr) + , mParentContentListener(nullptr) { } @@ -118,8 +120,33 @@ nsDSURIContentListener::DoContent(const char* aContentType, mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL); } + + // In case of multipart jpeg request (mjpeg) we don't really want to + // create new viewer since the one we already have is capable of + // rendering multipart jpeg correctly (see bug 625012) + nsCOMPtr baseChannel; + if (nsCOMPtr mpchan = do_QueryInterface(request)) { + mpchan->GetBaseChannel(getter_AddRefs(baseChannel)); + } + + bool reuseCV = baseChannel + && baseChannel == mExistingJPEGRequest + && nsDependentCString(aContentType).EqualsLiteral("image/jpeg"); + + if (mExistingJPEGStreamListener && reuseCV) { + nsRefPtr copy(mExistingJPEGStreamListener); + copy.forget(aContentHandler); + rv = NS_OK; + } else { + rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); + if (NS_SUCCEEDED(rv) && reuseCV) { + mExistingJPEGStreamListener = *aContentHandler; + } else { + mExistingJPEGStreamListener = nullptr; + } + mExistingJPEGRequest = baseChannel; + } - rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); if (rv == NS_ERROR_REMOTE_XUL) { request->Cancel(rv); diff --git a/docshell/base/nsDSURIContentListener.h b/docshell/base/nsDSURIContentListener.h index 038f153cfd71..f8c6a6994781 100644 --- a/docshell/base/nsDSURIContentListener.h +++ b/docshell/base/nsDSURIContentListener.h @@ -34,6 +34,8 @@ protected: void DropDocShellreference() { mDocShell = nullptr; + mExistingJPEGRequest = nullptr; + mExistingJPEGStreamListener = nullptr; } // Determine if X-Frame-Options allows content to be framed @@ -53,6 +55,9 @@ protected: XFOHeader aHeader); protected: nsDocShell* mDocShell; + // Hack to handle multipart images without creating a new viewer + nsCOMPtr mExistingJPEGStreamListener; + nsCOMPtr mExistingJPEGRequest; // Store the parent listener in either of these depending on // if supports weak references or not. Proper weak refs are diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp index d146cdf1d0db..7536861c736d 100644 --- a/image/src/imgRequest.cpp +++ b/image/src/imgRequest.cpp @@ -603,6 +603,8 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt if (mpchan) { mIsMultiPartChannel = true; statusTracker->SetIsMultipart(); + } else { + NS_ABORT_IF_FALSE(!mIsMultiPartChannel, "Something went wrong"); } // If we're not multipart, we shouldn't have an image yet From 2c45aa6d65f0f54560270aa49e27c79ea5e57563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Wed, 13 Aug 2014 07:19:00 -0400 Subject: [PATCH 15/86] Bug 820154 - Implement todo() in marionette-simpletest. r=jgriffin --- .../client/marionette/marionette_test.py | 25 ++++++-- .../tests/unit/test_simpletest_sanity.py | 46 +++++++++++---- testing/marionette/marionette-simpletest.js | 58 ++++++++++++++----- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/testing/marionette/client/marionette/marionette_test.py b/testing/marionette/client/marionette/marionette_test.py index 837843519eac..6faea129c75c 100644 --- a/testing/marionette/client/marionette/marionette_test.py +++ b/testing/marionette/client/marionette/marionette_test.py @@ -495,7 +495,7 @@ setReq.onerror = function() { 'expected timeout not triggered') if 'fail' in self.jsFile: - self.assertTrue(results['failed'] > 0, + self.assertTrue(len(results['failures']) > 0, "expected test failures didn't occur") else: logger = get_default_logger() @@ -504,10 +504,27 @@ setReq.onerror = function() { name = "got false, expected true" if failure.get('name') is None else failure['name'] logger.test_status(self.test_name, name, 'FAIL', message=diag) - self.assertEqual(0, results['failed'], - '%d tests failed' % (results['failed'])) + for failure in results['expectedFailures']: + diag = "" if failure.get('diag') is None else failure['diag'] + name = "got false, expected false" if failure.get('name') is None else failure['name'] + logger.test_status(self.test_name, name, 'FAIL', + expected='FAIL', message=diag) + for failure in results['unexpectedSuccesses']: + diag = "" if failure.get('diag') is None else failure['diag'] + name = "got true, expected false" if failure.get('name') is None else failure['name'] + logger.test_status(self.test_name, name, 'PASS', + expected='FAIL', message=diag) + self.assertEqual(0, len(results['failures']), + '%d tests failed' % len(results['failures'])) + if len(results['unexpectedSuccesses']) > 0: + raise _UnexpectedSuccess('') + if len(results['expectedFailures']) > 0: + raise _ExpectedFailure((AssertionError, AssertionError(''), None)) - self.assertTrue(results['passed'] + results['failed'] > 0, + self.assertTrue(results['passed'] + + len(results['failures']) + + len(results['expectedFailures']) + + len(results['unexpectedSuccesses']) > 0, 'no tests run') except ScriptTimeoutException: diff --git a/testing/marionette/client/marionette/tests/unit/test_simpletest_sanity.py b/testing/marionette/client/marionette/tests/unit/test_simpletest_sanity.py index d1d2d579cf97..fe51a1a47f7c 100644 --- a/testing/marionette/client/marionette/tests/unit/test_simpletest_sanity.py +++ b/testing/marionette/client/marionette/tests/unit/test_simpletest_sanity.py @@ -16,16 +16,16 @@ class SimpletestSanityTest(MarionetteTestCase): sentPass1 = "is(true, true, 'isTest3');" + self.callFinish sentPass2 = "is(true, true, 'isTest4');" + self.callFinish - self.assertEqual(1, self.marionette.execute_script(sentFail1)["failed"]) + self.assertEqual(1, len(self.marionette.execute_script(sentFail1)["failures"])) self.assertEqual(0, self.marionette.execute_script(sentFail2)["passed"]) self.assertEqual(1, self.marionette.execute_script(sentPass1)["passed"]) - self.assertEqual(0, self.marionette.execute_script(sentPass2)["failed"]) + self.assertEqual(0, len(self.marionette.execute_script(sentPass2)["failures"])) self.marionette.set_script_timeout(1000) - self.assertEqual(1, self.marionette.execute_async_script(sentFail1)["failed"]) + self.assertEqual(1, len(self.marionette.execute_async_script(sentFail1)["failures"])) self.assertEqual(0, self.marionette.execute_async_script(sentFail2)["passed"]) self.assertEqual(1, self.marionette.execute_async_script(sentPass1)["passed"]) - self.assertEqual(0, self.marionette.execute_async_script(sentPass2)["failed"]) + self.assertEqual(0, len(self.marionette.execute_async_script(sentPass2)["failures"])) self.marionette.set_context("content") runtests() @@ -39,15 +39,15 @@ class SimpletestSanityTest(MarionetteTestCase): sentPass1 = "isnot(true, false, 'isnotTest1');" + self.callFinish sentPass2 = "isnot(true, false, 'isnotTest2');" + self.callFinish - self.assertEqual(1, self.marionette.execute_script(sentFail1)["failed"]); + self.assertEqual(1, len(self.marionette.execute_script(sentFail1)["failures"])); self.assertEqual(0, self.marionette.execute_script(sentFail2)["passed"]); - self.assertEqual(0, self.marionette.execute_script(sentPass1)["failed"]); + self.assertEqual(0, len(self.marionette.execute_script(sentPass1)["failures"])); self.assertEqual(1, self.marionette.execute_script(sentPass2)["passed"]); self.marionette.set_script_timeout(1000) - self.assertEqual(1, self.marionette.execute_async_script(sentFail1)["failed"]); + self.assertEqual(1, len(self.marionette.execute_async_script(sentFail1)["failures"])); self.assertEqual(0, self.marionette.execute_async_script(sentFail2)["passed"]); - self.assertEqual(0, self.marionette.execute_async_script(sentPass1)["failed"]); + self.assertEqual(0, len(self.marionette.execute_async_script(sentPass1)["failures"])); self.assertEqual(1, self.marionette.execute_async_script(sentPass2)["passed"]); self.marionette.set_context("content") @@ -62,15 +62,15 @@ class SimpletestSanityTest(MarionetteTestCase): sentPass1 = "ok(1==1, 'testOk3');" + self.callFinish sentPass2 = "ok(1==1, 'testOk4');" + self.callFinish - self.assertEqual(1, self.marionette.execute_script(sentFail1)["failed"]); + self.assertEqual(1, len(self.marionette.execute_script(sentFail1)["failures"])); self.assertEqual(0, self.marionette.execute_script(sentFail2)["passed"]); - self.assertEqual(0, self.marionette.execute_script(sentPass1)["failed"]); + self.assertEqual(0, len(self.marionette.execute_script(sentPass1)["failures"])); self.assertEqual(1, self.marionette.execute_script(sentPass2)["passed"]); self.marionette.set_script_timeout(1000) - self.assertEqual(1, self.marionette.execute_async_script(sentFail1)["failed"]); + self.assertEqual(1, len(self.marionette.execute_async_script(sentFail1)["failures"])); self.assertEqual(0, self.marionette.execute_async_script(sentFail2)["passed"]); - self.assertEqual(0, self.marionette.execute_async_script(sentPass1)["failed"]); + self.assertEqual(0, len(self.marionette.execute_async_script(sentPass1)["failures"])); self.assertEqual(1, self.marionette.execute_async_script(sentPass2)["passed"]); self.marionette.set_context("content") @@ -78,3 +78,25 @@ class SimpletestSanityTest(MarionetteTestCase): self.marionette.set_context("chrome") runtests() + def test_todo(self): + def runtests(): + sentFail1 = "todo(1==1, 'testTodo1', TEST_UNEXPECTED_PASS, TEST_KNOWN_FAIL);" + self.callFinish + sentFail2 = "todo(1==1, 'testTodo2', TEST_UNEXPECTED_PASS, TEST_KNOWN_FAIL);" + self.callFinish + sentPass1 = "todo(1==2, 'testTodo3');" + self.callFinish + sentPass2 = "todo(1==2, 'testTodo4');" + self.callFinish + + self.assertEqual(1, len(self.marionette.execute_script(sentFail1)["unexpectedSuccesses"])); + self.assertEqual(0, len(self.marionette.execute_script(sentFail2)["expectedFailures"])); + self.assertEqual(0, len(self.marionette.execute_script(sentPass1)["unexpectedSuccesses"])); + self.assertEqual(1, len(self.marionette.execute_script(sentPass2)["expectedFailures"])); + + self.marionette.set_script_timeout(1000) + self.assertEqual(1, len(self.marionette.execute_async_script(sentFail1)["unexpectedSuccesses"])); + self.assertEqual(0, len(self.marionette.execute_async_script(sentFail2)["expectedFailures"])); + self.assertEqual(0, len(self.marionette.execute_async_script(sentPass1)["unexpectedSuccesses"])); + self.assertEqual(1, len(self.marionette.execute_async_script(sentPass2)["expectedFailures"])); + + self.marionette.set_context("content") + runtests() + self.marionette.set_context("chrome") + runtests() diff --git a/testing/marionette/marionette-simpletest.js b/testing/marionette/marionette-simpletest.js index 2ae9032ee82b..d07794b020da 100644 --- a/testing/marionette/marionette-simpletest.js +++ b/testing/marionette/marionette-simpletest.js @@ -16,33 +16,37 @@ this.Marionette = function Marionette(scope, window, context, logObj, timeout, this.heartbeatCallback = heartbeatCallback; this.testName = testName; this.TEST_UNEXPECTED_FAIL = "TEST-UNEXPECTED-FAIL"; + this.TEST_UNEXPECTED_PASS = "TEST-UNEXPECTED-PASS"; this.TEST_PASS = "TEST-PASS"; this.TEST_KNOWN_FAIL = "TEST-KNOWN-FAIL"; } Marionette.prototype = { - exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor', + exports: ['ok', 'is', 'isnot', 'todo', 'log', 'getLogs', 'generate_results', 'waitFor', 'runEmulatorCmd', 'runEmulatorShell', 'TEST_PASS', 'TEST_KNOWN_FAIL', - 'TEST_UNEXPECTED_FAIL'], + 'TEST_UNEXPECTED_FAIL', 'TEST_UNEXPECTED_PASS'], - ok: function Marionette__ok(condition, name, passString, failString, diag) { - this.heartbeatCallback(); - if (typeof(diag) == "undefined") { - diag = this.repr(condition) + " was " + !!condition + ", expected true"; - } - let test = {'result': !!condition, 'name': name, 'diag': diag}; + addTest: function Marionette__addTest(condition, name, passString, failString, diag, state) { + + let test = {'result': !!condition, 'name': name, 'diag': diag, 'state': state}; this.logResult(test, typeof(passString) == "undefined" ? this.TEST_PASS : passString, typeof(failString) == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString); this.tests.push(test); }, + ok: function Marionette__ok(condition, name, passString, failString) { + this.heartbeatCallback(); + let diag = this.repr(condition) + " was " + !!condition + ", expected true"; + this.addTest(condition, name, passString, failString, diag); + }, + is: function Marionette__is(a, b, name, passString, failString) { this.heartbeatCallback(); let pass = (a == b); let diag = pass ? this.repr(a) + " should equal " + this.repr(b) : "got " + this.repr(a) + ", expected " + this.repr(b); - this.ok(pass, name, passString, failString, diag); + this.addTest(pass, name, passString, failString, diag); }, isnot: function Marionette__isnot (a, b, name, passString, failString) { @@ -50,7 +54,18 @@ Marionette.prototype = { let pass = (a != b); let diag = pass ? this.repr(a) + " should not equal " + this.repr(b) : "didn't expect " + this.repr(a) + ", but got it"; - this.ok(pass, name, passString, failString, diag); + this.addTest(pass, name, passString, failString, diag); + }, + + todo: function Marionette__todo(condition, name, passString, failString) { + this.heartbeatCallback(); + let diag = this.repr(condition) + " was expected false"; + this.addTest(!condition, + name, + typeof(passString) == "undefined" ? this.TEST_KNOWN_FAIL : passString, + typeof(failString) == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString, + diag, + "todo"); }, log: function Marionette__log(msg, level) { @@ -71,21 +86,32 @@ Marionette.prototype = { generate_results: function Marionette__generate_results() { this.heartbeatCallback(); let passed = 0; - let failed = 0; let failures = []; + let expectedFailures = []; + let unexpectedSuccesses = []; for (let i in this.tests) { + let isTodo = (this.tests[i].state == "todo"); if(this.tests[i].result) { - passed++; + if (isTodo) { + expectedFailures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } + else { + passed++; + } } else { - failed++; - failures.push({'name': this.tests[i].name, - 'diag': this.tests[i].diag}); + if (isTodo) { + unexpectedSuccesses.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } + else { + failures.push({'name': this.tests[i].name, 'diag': this.tests[i].diag}); + } } } // Reset state in case this object is reused for more tests. this.tests = []; - return {"passed": passed, "failed": failed, "failures": failures}; + return {"passed": passed, "failures": failures, "expectedFailures": expectedFailures, + "unexpectedSuccesses": unexpectedSuccesses}; }, logToFile: function Marionette__logToFile(file) { From 0647fe4544c41d270190ee8784472c394e04ab23 Mon Sep 17 00:00:00 2001 From: Alex Bardas Date: Wed, 13 Aug 2014 13:29:00 -0400 Subject: [PATCH 16/86] Bug 999293 - [e10s] Make charset menu work. r=adw --- browser/base/content/browser.js | 41 +++---------------- .../customizableui/CustomizableWidgets.jsm | 6 +-- toolkit/content/browser-child.js | 6 +++ toolkit/content/widgets/browser.xml | 10 ++++- toolkit/content/widgets/remote-browser.xml | 12 +++++- toolkit/modules/RemoteWebProgress.jsm | 1 + 6 files changed, 35 insertions(+), 41 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 799ce84973eb..fd286166449e 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -30,7 +30,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDNSService", const nsIWebNavigation = Ci.nsIWebNavigation; var gLastBrowserCharset = null; -var gPrevCharset = null; var gProxyFavIcon = null; var gLastValidURLStr = ""; var gInPrintPreviewMode = false; @@ -242,7 +241,6 @@ XPCOMUtils.defineLazyGetter(this, "PageMenu", function() { * one listener that calls all real handlers. */ function pageShowEventHandlers(persisted) { - charsetLoadListener(); XULBrowserWindow.asyncUpdateUI(); // The PluginClickToPlay events are not fired when navigating using the @@ -3511,9 +3509,7 @@ function updateCharacterEncodingMenuState() // gBrowser is null on Mac when the menubar shows in the context of // non-browser windows. The above elements may be null depending on // what parts of the menubar are present. E.g. no app menu on Mac. - if (gBrowser && - gBrowser.docShell && - gBrowser.docShell.mayEnableCharacterEncodingMenu) { + if (gBrowser && gBrowser.selectedBrowser.mayEnableCharacterEncodingMenu) { if (charsetMenu) { charsetMenu.removeAttribute("disabled"); } @@ -5358,8 +5354,7 @@ function handleDroppedLink(event, url, name) function BrowserSetForcedCharacterSet(aCharset) { if (aCharset) { - gBrowser.docShell.gatherCharsetMenuTelemetry(); - gBrowser.docShell.charset = aCharset; + gBrowser.selectedBrowser.characterSet = aCharset; // Save the forced character-set if (!PrivateBrowsingUtils.isWindowPrivate(window)) PlacesUtils.setCharsetForURI(getWebNavigation().currentURI, aCharset); @@ -5372,35 +5367,11 @@ function BrowserCharsetReload() BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); } -function charsetMenuGetElement(parent, charset) { - return parent.getElementsByAttribute("charset", charset)[0]; -} - function UpdateCurrentCharset(target) { - // extract the charset from DOM - var wnd = document.commandDispatcher.focusedWindow; - if ((window == wnd) || (wnd == null)) wnd = window.content; - - // Uncheck previous item - if (gPrevCharset) { - var pref_item = charsetMenuGetElement(target, gPrevCharset); - if (pref_item) - pref_item.setAttribute('checked', 'false'); - } - - var menuitem = charsetMenuGetElement(target, CharsetMenu.foldCharset(wnd.document.characterSet)); - if (menuitem) { - menuitem.setAttribute('checked', 'true'); - } -} - -function charsetLoadListener() { - let currCharset = gBrowser.selectedBrowser.characterSet; - let charset = CharsetMenu.foldCharset(currCharset); - - if (charset.length > 0 && (charset != gLastBrowserCharset)) { - gPrevCharset = gLastBrowserCharset; - gLastBrowserCharset = charset; + for (let menuItem of target.getElementsByTagName("menuitem")) { + let isSelected = menuItem.getAttribute("charset") === + CharsetMenu.foldCharset(gBrowser.selectedBrowser.characterSet); + menuItem.setAttribute("checked", isSelected); } } diff --git a/browser/components/customizableui/CustomizableWidgets.jsm b/browser/components/customizableui/CustomizableWidgets.jsm index e95ce1f2eac8..b6924a61d298 100644 --- a/browser/components/customizableui/CustomizableWidgets.jsm +++ b/browser/components/customizableui/CustomizableWidgets.jsm @@ -735,8 +735,7 @@ const CustomizableWidgets = [{ maybeDisableMenu: function(aDocument) { let window = aDocument.defaultView; return !(window.gBrowser && - window.gBrowser.docShell && - window.gBrowser.docShell.mayEnableCharacterEncodingMenu); + window.gBrowser.selectedBrowser.mayEnableCharacterEncodingMenu); }, populateList: function(aDocument, aContainerId, aSection) { let containerElem = aDocument.getElementById(aContainerId); @@ -756,8 +755,7 @@ const CustomizableWidgets = [{ } }, updateCurrentCharset: function(aDocument) { - let content = aDocument.defaultView.content; - let currentCharset = content && content.document && content.document.characterSet; + let currentCharset = aDocument.defaultView.gBrowser.selectedBrowser.characterSet; currentCharset = CharsetMenu.foldCharset(currentCharset); let pinnedContainer = aDocument.getElementById("PanelUI-characterEncodingView-pinned"); diff --git a/toolkit/content/browser-child.js b/toolkit/content/browser-child.js index 9735f0e4d759..f94b8cb7b3dd 100644 --- a/toolkit/content/browser-child.js +++ b/toolkit/content/browser-child.js @@ -89,6 +89,7 @@ let WebProgressListener = { json.canGoForward = docShell.canGoForward; json.documentURI = content.document.documentURIObject.spec; json.charset = content.document.characterSet; + json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu; } sendAsyncMessage("Content:LocationChange", json, objects); @@ -353,6 +354,11 @@ addEventListener("TextZoomChange", function (aEvent) { } }, false); +addMessageListener("UpdateCharacterSet", function (aMessage) { + docShell.charset = aMessage.data.value; + docShell.gatherCharsetMenuTelemetry(); +}); + // The AddonsChild needs to be rooted so that it stays alive as long as // the tab. let AddonsChild; diff --git a/toolkit/content/widgets/browser.xml b/toolkit/content/widgets/browser.xml index 232717098ba7..10c1378f0bbc 100644 --- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -427,7 +427,15 @@ readonly="true"/> + + + + "" + + + + null + + null diff --git a/toolkit/modules/RemoteWebProgress.jsm b/toolkit/modules/RemoteWebProgress.jsm index 2528611450d4..a5af8263e2dd 100644 --- a/toolkit/modules/RemoteWebProgress.jsm +++ b/toolkit/modules/RemoteWebProgress.jsm @@ -173,6 +173,7 @@ RemoteWebProgressManager.prototype = { this._browser._characterSet = json.charset; this._browser._documentURI = newURI(json.documentURI); this._browser._imageDocument = null; + this._browser._mayEnableCharacterEncodingMenu = json.mayEnableCharacterEncodingMenu; } this._callProgressListeners("onLocationChange", webProgress, request, location, flags); From 2f9d49bc7593ad3e49422cbdf66b034d0185def8 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Wed, 13 Aug 2014 19:11:00 -0400 Subject: [PATCH 17/86] Bug 1046837 - Reset |mDispatchedDecodeMetadataTask| only after finishinig decoding metadata to avoid MediaDecoderStateMachine::CallDecodeMetadata() may run more than once. r=cpearce --- content/media/MediaDecoderStateMachine.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index c52b8a87fd80..f40cd88b3c47 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -1518,17 +1518,16 @@ MediaDecoderStateMachine::EnqueueDecodeMetadataTask() mDispatchedDecodeMetadataTask) { return NS_OK; } + + mDispatchedDecodeMetadataTask = true; RefPtr task( NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeMetadata)); nsresult rv = mDecodeTaskQueue->Dispatch(task); - if (NS_SUCCEEDED(rv)) { - mDispatchedDecodeMetadataTask = true; - } else { + if (NS_FAILED(rv)) { NS_WARNING("Dispatch ReadMetadata task failed."); - return rv; + mDispatchedDecodeMetadataTask = false; } - - return NS_OK; + return rv; } void @@ -1842,7 +1841,6 @@ void MediaDecoderStateMachine::CallDecodeMetadata() { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - AutoSetOnScopeExit unsetOnExit(mDispatchedDecodeMetadataTask, false); if (mState != DECODER_STATE_DECODING_METADATA) { return; } @@ -1874,6 +1872,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata() // change state to DECODER_STATE_WAIT_FOR_RESOURCES StartWaitForResources(); // affect values only if ReadMetadata succeeds + mDispatchedDecodeMetadataTask = false; return NS_OK; } } @@ -1996,6 +1995,7 @@ MediaDecoderStateMachine::FinishDecodeMetadata() StartPlayback(); } + mDispatchedDecodeMetadataTask = false; return NS_OK; } From 0fe8812f69a208fa3a765457eb5e12ae5e5c7456 Mon Sep 17 00:00:00 2001 From: Ahmed Kachkach Date: Fri, 8 Aug 2014 14:15:00 -0400 Subject: [PATCH 18/86] Bug 1051024 - Remove unstructured logs parsing in mochitest handlers. r=ahal --- testing/mochitest/runtests.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index af60e120b91b..5354970d5df5 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -1975,8 +1975,6 @@ class Mochitest(MochitestUtilsMixin): """record last test on harness""" if message['action'] == 'test_start': self.harness.lastTestSeen = message['test'] - elif message['action'] == 'log' and 'TEST-START' in message['message'] and '|' in message['message']: - self.harness.lastTestSeen = message['message'].split("|")[1].strip() return message def dumpScreenOnTimeout(self, message): @@ -1986,19 +1984,11 @@ class Mochitest(MochitestUtilsMixin): and 'message' in message and "Test timed out" in message['message']): self.harness.dumpScreen(self.utilityPath) - elif (not self.dump_screen_on_fail - and self.dump_screen_on_timeout - and message['action'] == 'log' - and 'TEST-UNEXPECTED-FAIL' in message['message'] - and 'Test timed out' in message['message']): - self.harness.dumpScreen(self.utilityPath) return message def dumpScreenOnFail(self, message): if self.dump_screen_on_fail and 'expected' in message and message['status'] == 'FAIL': self.harness.dumpScreen(self.utilityPath) - elif self.dump_screen_on_fail and message['action'] == 'log' and 'TEST-UNEXPECTED-FAIL' in message['message']: - self.harness.dumpScreen(self.utilityPath) return message def trackLSANLeaks(self, message): From b975af637c8567a61086b9ed8b5b309d7d9e5f4b Mon Sep 17 00:00:00 2001 From: Ahmed Kachkach Date: Tue, 12 Aug 2014 13:59:00 -0400 Subject: [PATCH 19/86] Bug 1051635 - Fix the missing error handling in TestRunner (structured logging). r=chmanchester --- testing/mochitest/tests/SimpleTest/TestRunner.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/testing/mochitest/tests/SimpleTest/TestRunner.js b/testing/mochitest/tests/SimpleTest/TestRunner.js index 65dd0e1cae5d..2aeb7eb8bc52 100644 --- a/testing/mochitest/tests/SimpleTest/TestRunner.js +++ b/testing/mochitest/tests/SimpleTest/TestRunner.js @@ -261,6 +261,11 @@ function StructuredLogger(name) { } else { dump('\n' + str + '\n'); } + + // Checking for error messages + if (message.expected || message.level === "ERROR") { + TestRunner.failureHandler(); + } }; /* Message validation. Only checking the action for now */ @@ -425,8 +430,11 @@ TestRunner.error = function(msg) { TestRunner.structuredLogger.error(msg); } else { dump(msg + "\n"); + TestRunner.failureHandler(); } +}; +TestRunner.failureHandler = function() { if (TestRunner.runUntilFailure) { TestRunner._haltTests = true; } @@ -469,7 +477,7 @@ TestRunner._makeIframe = function (url, retry) { return; } - TestRunner.structuredLogger.error("Unable to restore focus, expect failures and timeouts."); + TestRunner.structuredLogger.info("Error: Unable to restore focus, expect failures and timeouts."); } window.scrollTo(0, $('indicator').offsetTop); iframe.src = url; From 9c2d40f4ac322864b358aff89e996ca72d2e8bba Mon Sep 17 00:00:00 2001 From: Ahmed Kachkach Date: Wed, 13 Aug 2014 11:09:00 -0400 Subject: [PATCH 20/86] Bug 1052937 - Add a default value for mochitest assertions' name. r=ahal --- testing/mochitest/tests/SimpleTest/SimpleTest.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/mochitest/tests/SimpleTest/SimpleTest.js b/testing/mochitest/tests/SimpleTest/SimpleTest.js index 075e69a78dd6..7e221dc05601 100644 --- a/testing/mochitest/tests/SimpleTest/SimpleTest.js +++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js @@ -243,6 +243,9 @@ SimpleTest._cleanupFunctions = []; * Something like assert. **/ SimpleTest.ok = function (condition, name, diag) { + if (name === null || name === undefined) { + name = "undefined assertion name"; + } var test = {'result': !!condition, 'name': name, 'diag': diag}; var successInfo = {status:"PASS", expected:"PASS", message:"TEST-PASS"}; var failureInfo = {status:"FAIL", expected:"PASS", message:"TEST-UNEXPECTED-FAIL"}; From 4bd9fb18d1ee0b5477537b43e7b5a48cd2dc158d Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 17 Jul 2014 15:52:14 +1200 Subject: [PATCH 21/86] Bug 1022501 - Fix Windows falsely reporting support for MP4 in MP3. r=cpearce --- content/media/DecoderTraits.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/media/DecoderTraits.cpp b/content/media/DecoderTraits.cpp index 30e5db2b80a1..a4e535a9afa5 100644 --- a/content/media/DecoderTraits.cpp +++ b/content/media/DecoderTraits.cpp @@ -441,7 +441,8 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType, } #endif #ifdef MOZ_WMF - if (IsWMFSupportedType(nsDependentCString(aMIMEType))) { + if (Preferences::GetBool("media.fragmented-mp4.exposed", false) && + IsWMFSupportedType(nsDependentCString(aMIMEType))) { if (!aHaveRequestedCodecs) { return CANPLAY_MAYBE; } From 42cab9e34901470e68c7e0f3a14a7e3f1db9f858 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Fri, 15 Aug 2014 16:25:06 +1000 Subject: [PATCH 22/86] Bug 1022501 - Add MP3 support to MP4 demuxer. r=edwin --HG-- rename : content/media/fmp4/eme/EMEAACDecoder.cpp => content/media/fmp4/eme/EMEAudioDecoder.cpp rename : content/media/fmp4/eme/EMEAACDecoder.h => content/media/fmp4/eme/EMEAudioDecoder.h rename : content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp => content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp rename : content/media/fmp4/ffmpeg/FFmpegAACDecoder.h => content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h --- content/media/fmp4/BlankDecoderModule.cpp | 13 +++- content/media/fmp4/MP4Reader.cpp | 27 ++++--- content/media/fmp4/MP4Reader.h | 1 + content/media/fmp4/PlatformDecoderModule.cpp | 6 ++ content/media/fmp4/PlatformDecoderModule.h | 17 +++-- content/media/fmp4/apple/AppleATDecoder.cpp | 20 +++-- content/media/fmp4/apple/AppleATDecoder.h | 1 + .../media/fmp4/apple/AppleDecoderModule.cpp | 12 ++- content/media/fmp4/apple/AppleDecoderModule.h | 8 +- ...{EMEAACDecoder.cpp => EMEAudioDecoder.cpp} | 60 +++++++-------- .../{EMEAACDecoder.h => EMEAudioDecoder.h} | 24 +++--- content/media/fmp4/eme/EMEDecoderModule.cpp | 22 +++--- content/media/fmp4/eme/EMEDecoderModule.h | 6 +- content/media/fmp4/eme/moz.build | 4 +- ...gAACDecoder.cpp => FFmpegAudioDecoder.cpp} | 73 ++++++++++++++----- ...FmpegAACDecoder.h => FFmpegAudioDecoder.h} | 13 ++-- .../media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 6 +- .../media/fmp4/ffmpeg/FFmpegDecoderModule.h | 15 ++-- content/media/fmp4/ffmpeg/FFmpegLibs.h | 2 + content/media/fmp4/ffmpeg/libav53/moz.build | 2 +- content/media/fmp4/ffmpeg/libav54/moz.build | 2 +- content/media/fmp4/ffmpeg/libav55/moz.build | 2 +- content/media/fmp4/gonk/GonkDecoderModule.cpp | 6 +- content/media/fmp4/gonk/GonkDecoderModule.h | 6 +- content/media/fmp4/wmf/WMFDecoderModule.cpp | 6 +- content/media/fmp4/wmf/WMFDecoderModule.h | 6 +- media/libstagefright/binding/DecoderData.cpp | 3 +- media/libstagefright/binding/mp4_demuxer.cpp | 11 ++- .../media/libstagefright/MPEG4Extractor.cpp | 5 +- 29 files changed, 234 insertions(+), 145 deletions(-) rename content/media/fmp4/eme/{EMEAACDecoder.cpp => EMEAudioDecoder.cpp} (84%) rename content/media/fmp4/eme/{EMEAACDecoder.h => EMEAudioDecoder.h} (85%) rename content/media/fmp4/ffmpeg/{FFmpegAACDecoder.cpp => FFmpegAudioDecoder.cpp} (54%) rename content/media/fmp4/ffmpeg/{FFmpegAACDecoder.h => FFmpegAudioDecoder.h} (68%) diff --git a/content/media/fmp4/BlankDecoderModule.cpp b/content/media/fmp4/BlankDecoderModule.cpp index 637d8fdf2673..25d8b63311e9 100644 --- a/content/media/fmp4/BlankDecoderModule.cpp +++ b/content/media/fmp4/BlankDecoderModule.cpp @@ -229,9 +229,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { BlankAudioDataCreator* creator = new BlankAudioDataCreator( aConfig.channel_count, aConfig.samples_per_second); @@ -241,6 +241,13 @@ public: aCallback); return decoder.forget(); } + + virtual bool + SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE + { + return true; + } + }; PlatformDecoderModule* CreateBlankDecoderModule() diff --git a/content/media/fmp4/MP4Reader.cpp b/content/media/fmp4/MP4Reader.cpp index 5f2f536ffa45..7341564fccfe 100644 --- a/content/media/fmp4/MP4Reader.cpp +++ b/content/media/fmp4/MP4Reader.cpp @@ -288,6 +288,14 @@ MP4Reader::ExtractCryptoInitData(nsTArray& aInitData) } } +bool +MP4Reader::IsSupportedAudioMimeType(const char* aMimeType) +{ + return (!strcmp(aMimeType, "audio/mpeg") || + !strcmp(aMimeType, "audio/mp4a-latm")) && + mPlatform->SupportsAudioMimeType(aMimeType); +} + nsresult MP4Reader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) @@ -296,13 +304,6 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, bool ok = mDemuxer->Init(); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); - mInfo.mAudio.mHasAudio = mAudio.mActive = mDemuxer->HasValidAudio(); - const AudioDecoderConfig& audio = mDemuxer->AudioConfig(); - // If we have audio, we *only* allow AAC to be decoded. - if (mInfo.mAudio.mHasAudio && strcmp(audio.mime_type, "audio/mp4a-latm")) { - return NS_ERROR_FAILURE; - } - mInfo.mVideo.mHasVideo = mVideo.mActive = mDemuxer->HasValidVideo(); const VideoDecoderConfig& video = mDemuxer->VideoConfig(); // If we have video, we *only* allow H.264 to be decoded. @@ -370,14 +371,18 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE); } - if (HasAudio()) { + if (mDemuxer->HasValidAudio()) { const AudioDecoderConfig& audio = mDemuxer->AudioConfig(); + mInfo.mAudio.mHasAudio = mAudio.mActive = true; + if (mInfo.mAudio.mHasAudio && !IsSupportedAudioMimeType(audio.mime_type)) { + return NS_ERROR_FAILURE; + } mInfo.mAudio.mRate = audio.samples_per_second; mInfo.mAudio.mChannels = audio.channel_count; mAudio.mCallback = new DecoderCallback(this, kAudio); - mAudio.mDecoder = mPlatform->CreateAACDecoder(audio, - mAudio.mTaskQueue, - mAudio.mCallback); + mAudio.mDecoder = mPlatform->CreateAudioDecoder(audio, + mAudio.mTaskQueue, + mAudio.mCallback); NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE); nsresult rv = mAudio.mDecoder->Init(); NS_ENSURE_SUCCESS(rv, rv); diff --git a/content/media/fmp4/MP4Reader.h b/content/media/fmp4/MP4Reader.h index 6bc00ad18b31..6fa9cbe2278d 100644 --- a/content/media/fmp4/MP4Reader.h +++ b/content/media/fmp4/MP4Reader.h @@ -87,6 +87,7 @@ private: void Flush(mp4_demuxer::TrackType aTrack); void DrainComplete(mp4_demuxer::TrackType aTrack); void UpdateIndex(); + bool IsSupportedAudioMimeType(const char* aMimeType); void NotifyResourcesStatusChanged(); bool IsWaitingOnCodecResource(); bool IsWaitingOnCDMResource(); diff --git a/content/media/fmp4/PlatformDecoderModule.cpp b/content/media/fmp4/PlatformDecoderModule.cpp index c19b03bceedc..cd145b5a6ad0 100644 --- a/content/media/fmp4/PlatformDecoderModule.cpp +++ b/content/media/fmp4/PlatformDecoderModule.cpp @@ -153,4 +153,10 @@ PlatformDecoderModule::Create() return nullptr; } +bool +PlatformDecoderModule::SupportsAudioMimeType(const char* aMimeType) +{ + return !strcmp(aMimeType, "audio/mp4a-latm"); +} + } // namespace mozilla diff --git a/content/media/fmp4/PlatformDecoderModule.h b/content/media/fmp4/PlatformDecoderModule.h index 9c677139a8e5..d8bf178eafd0 100644 --- a/content/media/fmp4/PlatformDecoderModule.h +++ b/content/media/fmp4/PlatformDecoderModule.h @@ -35,8 +35,8 @@ class CDMProxy; typedef int64_t Microseconds; // The PlatformDecoderModule interface is used by the MP4Reader to abstract -// access to the H264 and AAC decoders provided by various platforms. It -// may be extended to support other codecs in future. Each platform (Windows, +// access to the H264 and Audio (AAC/MP3) decoders provided by various platforms. +// It may be extended to support other codecs in future. Each platform (Windows, // MacOSX, Linux, B2G etc) must implement a PlatformDecoderModule to provide // access to its decoders in order to get decompressed H.264/AAC from the // MP4Reader. @@ -103,7 +103,7 @@ public: MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback) = 0; - // Creates an AAC decoder with the specified properties. + // Creates an Audio decoder with the specified properties. // Asynchronous decoding of audio should be done in runnables dispatched to // aAudioTaskQueue. If the task queue isn't needed, the decoder should // not hold a reference to it. @@ -114,9 +114,14 @@ public: // It is safe to store a reference to aConfig. // This is called on the decode task queue. virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) = 0; + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) = 0; + + // An audio decoder module must support AAC by default. + // If more audio codec is to be supported, SupportsAudioMimeType will have + // to be extended + virtual bool SupportsAudioMimeType(const char* aMimeType); virtual ~PlatformDecoderModule() {} diff --git a/content/media/fmp4/apple/AppleATDecoder.cpp b/content/media/fmp4/apple/AppleATDecoder.cpp index f96f102988e5..a0916aaf6bd0 100644 --- a/content/media/fmp4/apple/AppleATDecoder.cpp +++ b/content/media/fmp4/apple/AppleATDecoder.cpp @@ -37,13 +37,20 @@ AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, , mHaveOutput(false) { MOZ_COUNT_CTOR(AppleATDecoder); - LOG("Creating Apple AudioToolbox AAC decoder"); + LOG("Creating Apple AudioToolbox Audio decoder"); LOG("Audio Decoder configuration: %s %d Hz %d channels %d bits per channel", mConfig.mime_type, mConfig.samples_per_second, mConfig.channel_count, mConfig.bits_per_sample); - // TODO: Verify aConfig.mime_type. + + if (!strcmp(aConfig.mime_type, "audio/mpeg")) { + mFileType = kAudioFileMP3Type; + } else if (!strcmp(aConfig.mime_type, "audio/mp4a-latm")) { + mFileType = kAudioFileAAC_ADTSType; + } else { + mFileType = 0; + } } AppleATDecoder::~AppleATDecoder() @@ -79,12 +86,15 @@ _SampleCallback(void *aDecoder, nsresult AppleATDecoder::Init() { - LOG("Initializing Apple AudioToolbox AAC decoder"); - AudioFileTypeID fileType = kAudioFileAAC_ADTSType; + if (!mFileType) { + NS_ERROR("Non recognised format"); + return NS_ERROR_FAILURE; + } + LOG("Initializing Apple AudioToolbox Audio decoder"); OSStatus rv = AudioFileStreamOpen(this, _MetadataCallback, _SampleCallback, - fileType, + mFileType, &mStream); if (rv) { NS_ERROR("Couldn't open AudioFileStream"); diff --git a/content/media/fmp4/apple/AppleATDecoder.h b/content/media/fmp4/apple/AppleATDecoder.h index b236a1974d96..6c84a9076633 100644 --- a/content/media/fmp4/apple/AppleATDecoder.h +++ b/content/media/fmp4/apple/AppleATDecoder.h @@ -53,6 +53,7 @@ private: int64_t mSamplePosition; bool mHaveOutput; AudioStreamBasicDescription mOutputFormat; + AudioFileTypeID mFileType; void SetupDecoder(); void SubmitSample(nsAutoPtr aSample); diff --git a/content/media/fmp4/apple/AppleDecoderModule.cpp b/content/media/fmp4/apple/AppleDecoderModule.cpp index eb037bae9152..fc4919c7fa66 100644 --- a/content/media/fmp4/apple/AppleDecoderModule.cpp +++ b/content/media/fmp4/apple/AppleDecoderModule.cpp @@ -87,13 +87,19 @@ AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCo } already_AddRefed -AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +AppleDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback); return decoder.forget(); } +bool +AppleDecoderModule::SupportsAudioMimeType(const char* aMimeType) +{ + return !strcmp(aMimeType, "audio/mp4a-latm") || !strcmp(aMimeType, "audio/mpeg"); +} + } // namespace mozilla diff --git a/content/media/fmp4/apple/AppleDecoderModule.h b/content/media/fmp4/apple/AppleDecoderModule.h index 21943f808eec..639ec8a730e6 100644 --- a/content/media/fmp4/apple/AppleDecoderModule.h +++ b/content/media/fmp4/apple/AppleDecoderModule.h @@ -34,9 +34,11 @@ public: // Decode thread. virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + + virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE; static void Init(); private: diff --git a/content/media/fmp4/eme/EMEAACDecoder.cpp b/content/media/fmp4/eme/EMEAudioDecoder.cpp similarity index 84% rename from content/media/fmp4/eme/EMEAACDecoder.cpp rename to content/media/fmp4/eme/EMEAudioDecoder.cpp index fa32b5e1395a..94aec13b8a27 100644 --- a/content/media/fmp4/eme/EMEAACDecoder.cpp +++ b/content/media/fmp4/eme/EMEAudioDecoder.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "EMEAACDecoder.h" +#include "EMEAudioDecoder.h" #include "mp4_demuxer/DecoderData.h" #include "mozilla/EMELog.h" #include "gmp-audio-host.h" @@ -18,10 +18,10 @@ namespace mozilla { -EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy, - const AudioDecoderConfig& aConfig, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback) +EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy, + const AudioDecoderConfig& aConfig, + MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback) : mAudioRate(0) , mAudioBytesPerSample(0) , mAudioChannels(0) @@ -34,17 +34,17 @@ EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy, , mConfig(aConfig) , mTaskQueue(aTaskQueue) , mCallback(aCallback) - , mMonitor("EMEAACDecoder") + , mMonitor("EMEAudioDecoder") , mFlushComplete(false) { } -EMEAACDecoder::~EMEAACDecoder() +EMEAudioDecoder::~EMEAudioDecoder() { } nsresult -EMEAACDecoder::Init() +EMEAudioDecoder::Init() { // Note: this runs on the decode task queue. @@ -65,7 +65,7 @@ EMEAACDecoder::Init() } nsresult -EMEAACDecoder::Input(MP4Sample* aSample) +EMEAudioDecoder::Input(MP4Sample* aSample) { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. @@ -77,7 +77,7 @@ EMEAACDecoder::Input(MP4Sample* aSample) } nsresult -EMEAACDecoder::Flush() +EMEAudioDecoder::Flush() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. @@ -87,7 +87,7 @@ EMEAACDecoder::Flush() } nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpFlush); + task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpFlush); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); @@ -102,34 +102,34 @@ EMEAACDecoder::Flush() } nsresult -EMEAACDecoder::Drain() +EMEAudioDecoder::Drain() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpDrain); + task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpDrain); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult -EMEAACDecoder::Shutdown() +EMEAudioDecoder::Shutdown() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpShutdown); + task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpShutdown); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } void -EMEAACDecoder::Decoded(const nsTArray& aPCM, - uint64_t aTimeStamp, - uint32_t aChannels, - uint32_t aRate) +EMEAudioDecoder::Decoded(const nsTArray& aPCM, + uint64_t aTimeStamp, + uint32_t aChannels, + uint32_t aRate) { MOZ_ASSERT(IsOnGMPThread()); @@ -192,21 +192,21 @@ EMEAACDecoder::Decoded(const nsTArray& aPCM, } void -EMEAACDecoder::InputDataExhausted() +EMEAudioDecoder::InputDataExhausted() { MOZ_ASSERT(IsOnGMPThread()); mCallback->InputExhausted(); } void -EMEAACDecoder::DrainComplete() +EMEAudioDecoder::DrainComplete() { MOZ_ASSERT(IsOnGMPThread()); mCallback->DrainComplete(); } void -EMEAACDecoder::ResetComplete() +EMEAudioDecoder::ResetComplete() { MOZ_ASSERT(IsOnGMPThread()); mMustRecaptureAudioPosition = true; @@ -218,23 +218,23 @@ EMEAACDecoder::ResetComplete() } void -EMEAACDecoder::Error(GMPErr aErr) +EMEAudioDecoder::Error(GMPErr aErr) { MOZ_ASSERT(IsOnGMPThread()); - EME_LOG("EMEAACDecoder::Error"); + EME_LOG("EMEAudioDecoder::Error"); mCallback->Error(); GmpShutdown(); } void -EMEAACDecoder::Terminated() +EMEAudioDecoder::Terminated() { MOZ_ASSERT(IsOnGMPThread()); GmpShutdown(); } nsresult -EMEAACDecoder::GmpInit() +EMEAudioDecoder::GmpInit() { MOZ_ASSERT(IsOnGMPThread()); @@ -266,7 +266,7 @@ EMEAACDecoder::GmpInit() } nsresult -EMEAACDecoder::GmpInput(MP4Sample* aSample) +EMEAudioDecoder::GmpInput(MP4Sample* aSample) { MOZ_ASSERT(IsOnGMPThread()); nsAutoPtr sample(aSample); @@ -296,7 +296,7 @@ EMEAACDecoder::GmpInput(MP4Sample* aSample) } void -EMEAACDecoder::GmpFlush() +EMEAudioDecoder::GmpFlush() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP || NS_FAILED(mGMP->Reset())) { @@ -308,7 +308,7 @@ EMEAACDecoder::GmpFlush() } void -EMEAACDecoder::GmpDrain() +EMEAudioDecoder::GmpDrain() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP || NS_FAILED(mGMP->Drain())) { @@ -317,7 +317,7 @@ EMEAACDecoder::GmpDrain() } void -EMEAACDecoder::GmpShutdown() +EMEAudioDecoder::GmpShutdown() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP) { diff --git a/content/media/fmp4/eme/EMEAACDecoder.h b/content/media/fmp4/eme/EMEAudioDecoder.h similarity index 85% rename from content/media/fmp4/eme/EMEAACDecoder.h rename to content/media/fmp4/eme/EMEAudioDecoder.h index 9232cdbaa92e..2d4bcb7b857d 100644 --- a/content/media/fmp4/eme/EMEAACDecoder.h +++ b/content/media/fmp4/eme/EMEAudioDecoder.h @@ -16,18 +16,18 @@ namespace mozilla { -class EMEAACDecoder : public MediaDataDecoder - , public GMPAudioDecoderProxyCallback +class EMEAudioDecoder : public MediaDataDecoder + , public GMPAudioDecoderProxyCallback { typedef mp4_demuxer::MP4Sample MP4Sample; typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig; public: - EMEAACDecoder(CDMProxy* aProxy, - const AudioDecoderConfig& aConfig, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback); + EMEAudioDecoder(CDMProxy* aProxy, + const AudioDecoderConfig& aConfig, + MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback); - ~EMEAACDecoder(); + ~EMEAudioDecoder(); // MediaDataDecoder implementation. virtual nsresult Init() MOZ_OVERRIDE; @@ -51,7 +51,7 @@ private: class DeliverSample : public nsRunnable { public: - DeliverSample(EMEAACDecoder* aDecoder, + DeliverSample(EMEAudioDecoder* aDecoder, mp4_demuxer::MP4Sample* aSample) : mDecoder(aDecoder) , mSample(aSample) @@ -62,13 +62,13 @@ private: return NS_OK; } private: - nsRefPtr mDecoder; + nsRefPtr mDecoder; nsAutoPtr mSample; }; class InitTask : public nsRunnable { public: - InitTask(EMEAACDecoder* aDecoder) + InitTask(EMEAudioDecoder* aDecoder) : mDecoder(aDecoder) {} NS_IMETHOD Run() { @@ -76,7 +76,7 @@ private: return NS_OK; } nsresult mResult; - EMEAACDecoder* mDecoder; + EMEAudioDecoder* mDecoder; }; nsresult GmpInit(); @@ -114,4 +114,4 @@ private: } // namespace mozilla -#endif \ No newline at end of file +#endif diff --git a/content/media/fmp4/eme/EMEDecoderModule.cpp b/content/media/fmp4/eme/EMEDecoderModule.cpp index 65c6d9f555c4..968e12d90b0b 100644 --- a/content/media/fmp4/eme/EMEDecoderModule.cpp +++ b/content/media/fmp4/eme/EMEDecoderModule.cpp @@ -19,7 +19,7 @@ #include "SharedThreadPool.h" #include "mozilla/EMELog.h" #include "EMEH264Decoder.h" -#include "EMEAACDecoder.h" +#include "EMEAudioDecoder.h" #include namespace mozilla { @@ -227,21 +227,21 @@ EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig, } already_AddRefed -EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { if (mCDMDecodesAudio) { - nsRefPtr decoder(new EMEAACDecoder(mProxy, - aConfig, - aAudioTaskQueue, - aCallback)); + nsRefPtr decoder(new EMEAudioDecoder(mProxy, + aConfig, + aAudioTaskQueue, + aCallback)); return decoder.forget(); } - nsRefPtr decoder(mPDM->CreateAACDecoder(aConfig, - aAudioTaskQueue, - aCallback)); + nsRefPtr decoder(mPDM->CreateAudioDecoder(aConfig, + aAudioTaskQueue, + aCallback)); if (!decoder) { return nullptr; } diff --git a/content/media/fmp4/eme/EMEDecoderModule.h b/content/media/fmp4/eme/EMEDecoderModule.h index afe0212f35be..89ec4597ec9e 100644 --- a/content/media/fmp4/eme/EMEDecoderModule.h +++ b/content/media/fmp4/eme/EMEDecoderModule.h @@ -42,9 +42,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; private: nsRefPtr mProxy; diff --git a/content/media/fmp4/eme/moz.build b/content/media/fmp4/eme/moz.build index d22505cf61f5..19f484899fa0 100644 --- a/content/media/fmp4/eme/moz.build +++ b/content/media/fmp4/eme/moz.build @@ -5,13 +5,13 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS += [ - 'EMEAACDecoder.h', + 'EMEAudioDecoder.h', 'EMEDecoderModule.h', 'EMEH264Decoder.h', ] UNIFIED_SOURCES += [ - 'EMEAACDecoder.cpp', + 'EMEAudioDecoder.cpp', 'EMEDecoderModule.cpp', 'EMEH264Decoder.cpp', ] diff --git a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp b/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp similarity index 54% rename from content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp rename to content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp index 4c224b5583e2..fcac1b13144f 100644 --- a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp @@ -7,7 +7,7 @@ #include "MediaTaskQueue.h" #include "FFmpegRuntimeLinker.h" -#include "FFmpegAACDecoder.h" +#include "FFmpegAudioDecoder.h" #define MAX_CHANNELS 16 @@ -16,16 +16,17 @@ typedef mp4_demuxer::MP4Sample MP4Sample; namespace mozilla { -FFmpegAACDecoder::FFmpegAACDecoder( +FFmpegAudioDecoder::FFmpegAudioDecoder( MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, const mp4_demuxer::AudioDecoderConfig& aConfig) - : FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_AAC), mCallback(aCallback) + : FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mime_type)) + , mCallback(aCallback) { - MOZ_COUNT_CTOR(FFmpegAACDecoder); + MOZ_COUNT_CTOR(FFmpegAudioDecoder); } nsresult -FFmpegAACDecoder::Init() +FFmpegAudioDecoder::Init() { nsresult rv = FFmpegDataDecoder::Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -34,24 +35,44 @@ FFmpegAACDecoder::Init() } static AudioDataValue* -CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples) +CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames) { MOZ_ASSERT(aNumChannels <= MAX_CHANNELS); nsAutoArrayPtr audio( - new AudioDataValue[aNumChannels * aNumSamples]); - - AudioDataValue** data = reinterpret_cast(aFrame->data); + new AudioDataValue[aNumChannels * aNumAFrames]); if (aFrame->format == AV_SAMPLE_FMT_FLT) { // Audio data already packed. No need to do anything other than copy it // into a buffer we own. - memcpy(audio, data[0], aNumChannels * aNumSamples * sizeof(AudioDataValue)); + memcpy(audio, aFrame->data[0], + aNumChannels * aNumAFrames * sizeof(AudioDataValue)); } else if (aFrame->format == AV_SAMPLE_FMT_FLTP) { // Planar audio data. Pack it into something we can understand. - for (uint32_t channel = 0; channel < aNumChannels; channel++) { - for (uint32_t sample = 0; sample < aNumSamples; sample++) { - audio[sample * aNumChannels + channel] = data[channel][sample]; + AudioDataValue* tmp = audio; + AudioDataValue** data = reinterpret_cast(aFrame->data); + for (uint32_t frame = 0; frame < aNumAFrames; frame++) { + for (uint32_t channel = 0; channel < aNumChannels; channel++) { + *tmp++ = data[channel][frame]; + } + } + } else if (aFrame->format == AV_SAMPLE_FMT_S16) { + // Audio data already packed. Need to convert from S16 to 32 bits Float + AudioDataValue* tmp = audio; + int16_t* data = reinterpret_cast(aFrame->data)[0]; + for (uint32_t frame = 0; frame < aNumAFrames; frame++) { + for (uint32_t channel = 0; channel < aNumChannels; channel++) { + *tmp++ = AudioSampleToFloat(*data++); + } + } + } else if (aFrame->format == AV_SAMPLE_FMT_S16P) { + // Planar audio data. Convert it from S16 to 32 bits float + // and pack it into something we can understand. + AudioDataValue* tmp = audio; + int16_t** data = reinterpret_cast(aFrame->data); + for (uint32_t frame = 0; frame < aNumAFrames; frame++) { + for (uint32_t channel = 0; channel < aNumChannels; channel++) { + *tmp++ = AudioSampleToFloat(data[channel][frame]); } } } @@ -60,7 +81,7 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples) } void -FFmpegAACDecoder::DecodePacket(MP4Sample* aSample) +FFmpegAudioDecoder::DecodePacket(MP4Sample* aSample) { AVPacket packet; av_init_packet(&packet); @@ -107,24 +128,38 @@ FFmpegAACDecoder::DecodePacket(MP4Sample* aSample) } nsresult -FFmpegAACDecoder::Input(MP4Sample* aSample) +FFmpegAudioDecoder::Input(MP4Sample* aSample) { mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg >( - this, &FFmpegAACDecoder::DecodePacket, nsAutoPtr(aSample))); + this, &FFmpegAudioDecoder::DecodePacket, nsAutoPtr(aSample))); return NS_OK; } nsresult -FFmpegAACDecoder::Drain() +FFmpegAudioDecoder::Drain() { mCallback->DrainComplete(); return NS_OK; } -FFmpegAACDecoder::~FFmpegAACDecoder() +AVCodecID +FFmpegAudioDecoder::GetCodecId(const char* aMimeType) { - MOZ_COUNT_DTOR(FFmpegAACDecoder); + if (!strcmp(aMimeType, "audio/mpeg")) { + return AV_CODEC_ID_MP3; + } + + if (!strcmp(aMimeType, "audio/mp4a-latm")) { + return AV_CODEC_ID_AAC; + } + + return AV_CODEC_ID_NONE; +} + +FFmpegAudioDecoder::~FFmpegAudioDecoder() +{ + MOZ_COUNT_DTOR(FFmpegAudioDecoder); } } // namespace mozilla diff --git a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.h b/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h similarity index 68% rename from content/media/fmp4/ffmpeg/FFmpegAACDecoder.h rename to content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h index 446a4082f142..9f7bfa6b9ad1 100644 --- a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.h +++ b/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h @@ -13,22 +13,23 @@ namespace mozilla { -template class FFmpegAACDecoder +template class FFmpegAudioDecoder { }; template <> -class FFmpegAACDecoder : public FFmpegDataDecoder +class FFmpegAudioDecoder : public FFmpegDataDecoder { public: - FFmpegAACDecoder(MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback, - const mp4_demuxer::AudioDecoderConfig& aConfig); - virtual ~FFmpegAACDecoder(); + FFmpegAudioDecoder(MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback, + const mp4_demuxer::AudioDecoderConfig& aConfig); + virtual ~FFmpegAudioDecoder(); virtual nsresult Init() MOZ_OVERRIDE; virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE; virtual nsresult Drain() MOZ_OVERRIDE; + static AVCodecID GetCodecId(const char* aMimeType); private: void DecodePacket(mp4_demuxer::MP4Sample* aSample); diff --git a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index 1388c8808593..89fdc3ec25e6 100644 --- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -108,8 +108,10 @@ FFmpegDataDecoder::Init() if (mCodecContext->codec_type == AVMEDIA_TYPE_AUDIO && mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT && - mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP) { - NS_WARNING("FFmpeg AAC decoder outputs unsupported audio format."); + mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP && + mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 && + mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16P) { + NS_WARNING("FFmpeg audio decoder outputs unsupported audio format."); return NS_ERROR_FAILURE; } diff --git a/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h b/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h index b3f9bf9161c2..6f54f18fb27b 100644 --- a/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h +++ b/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h @@ -8,7 +8,7 @@ #define __FFmpegDecoderModule_h__ #include "PlatformDecoderModule.h" -#include "FFmpegAACDecoder.h" +#include "FFmpegAudioDecoder.h" #include "FFmpegH264Decoder.h" namespace mozilla @@ -39,14 +39,19 @@ public: } virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { nsRefPtr decoder = - new FFmpegAACDecoder(aAudioTaskQueue, aCallback, aConfig); + new FFmpegAudioDecoder(aAudioTaskQueue, aCallback, aConfig); return decoder.forget(); } + + virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE + { + return FFmpegAudioDecoder::GetCodecId(aMimeType) != AV_CODEC_ID_NONE; + } }; } // namespace mozilla diff --git a/content/media/fmp4/ffmpeg/FFmpegLibs.h b/content/media/fmp4/ffmpeg/FFmpegLibs.h index 22050d58860f..aad71552f210 100644 --- a/content/media/fmp4/ffmpeg/FFmpegLibs.h +++ b/content/media/fmp4/ffmpeg/FFmpegLibs.h @@ -18,6 +18,8 @@ extern "C" { #if LIBAVCODEC_VERSION_MAJOR < 55 #define AV_CODEC_ID_H264 CODEC_ID_H264 #define AV_CODEC_ID_AAC CODEC_ID_AAC +#define AV_CODEC_ID_MP3 CODEC_ID_MP3 +#define AV_CODEC_ID_NONE CODEC_ID_NONE typedef CodecID AVCodecID; #endif diff --git a/content/media/fmp4/ffmpeg/libav53/moz.build b/content/media/fmp4/ffmpeg/libav53/moz.build index 25650064b756..d9053cff4a1e 100644 --- a/content/media/fmp4/ffmpeg/libav53/moz.build +++ b/content/media/fmp4/ffmpeg/libav53/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAACDecoder.cpp', + '../FFmpegAudioDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/ffmpeg/libav54/moz.build b/content/media/fmp4/ffmpeg/libav54/moz.build index 25650064b756..d9053cff4a1e 100644 --- a/content/media/fmp4/ffmpeg/libav54/moz.build +++ b/content/media/fmp4/ffmpeg/libav54/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAACDecoder.cpp', + '../FFmpegAudioDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/ffmpeg/libav55/moz.build b/content/media/fmp4/ffmpeg/libav55/moz.build index 234f4e24fe01..5d48e219aef8 100644 --- a/content/media/fmp4/ffmpeg/libav55/moz.build +++ b/content/media/fmp4/ffmpeg/libav55/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAACDecoder.cpp', + '../FFmpegAudioDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/gonk/GonkDecoderModule.cpp b/content/media/fmp4/gonk/GonkDecoderModule.cpp index 022fd3035051..d1f739da6e1d 100644 --- a/content/media/fmp4/gonk/GonkDecoderModule.cpp +++ b/content/media/fmp4/gonk/GonkDecoderModule.cpp @@ -48,9 +48,9 @@ GonkDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCon } already_AddRefed -GonkDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +GonkDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig), aAudioTaskQueue, diff --git a/content/media/fmp4/gonk/GonkDecoderModule.h b/content/media/fmp4/gonk/GonkDecoderModule.h index 95c0e08a4cf5..edda66f4d086 100644 --- a/content/media/fmp4/gonk/GonkDecoderModule.h +++ b/content/media/fmp4/gonk/GonkDecoderModule.h @@ -29,9 +29,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; static void Init(); }; diff --git a/content/media/fmp4/wmf/WMFDecoderModule.cpp b/content/media/fmp4/wmf/WMFDecoderModule.cpp index 55d3deb38ddd..00f390e2fe25 100644 --- a/content/media/fmp4/wmf/WMFDecoderModule.cpp +++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp @@ -81,9 +81,9 @@ WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConf } already_AddRefed -WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +WMFDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig), diff --git a/content/media/fmp4/wmf/WMFDecoderModule.h b/content/media/fmp4/wmf/WMFDecoderModule.h index d92d1281b412..b2f2b58e79ee 100644 --- a/content/media/fmp4/wmf/WMFDecoderModule.h +++ b/content/media/fmp4/wmf/WMFDecoderModule.h @@ -30,9 +30,9 @@ public: MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; virtual already_AddRefed - CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; // Called on main thread. static void Init(); diff --git a/media/libstagefright/binding/DecoderData.cpp b/media/libstagefright/binding/DecoderData.cpp index 32c1d5e1ceff..69673d4cea7e 100644 --- a/media/libstagefright/binding/DecoderData.cpp +++ b/media/libstagefright/binding/DecoderData.cpp @@ -8,6 +8,7 @@ #include "mp4_demuxer/DecoderData.h" #include "media/stagefright/MetaData.h" #include "media/stagefright/MediaBuffer.h" +#include "media/stagefright/MediaDefs.h" #include "media/stagefright/Utils.h" #include "mozilla/ArrayUtils.h" #include "include/ESDS.h" @@ -159,7 +160,7 @@ bool AudioDecoderConfig::IsValid() { return channel_count > 0 && samples_per_second > 0 && frequency_index > 0 && - aac_profile > 0; + (mime_type != MEDIA_MIMETYPE_AUDIO_AAC || aac_profile > 0); } void diff --git a/media/libstagefright/binding/mp4_demuxer.cpp b/media/libstagefright/binding/mp4_demuxer.cpp index 5daf7dd75bf9..c72009094412 100644 --- a/media/libstagefright/binding/mp4_demuxer.cpp +++ b/media/libstagefright/binding/mp4_demuxer.cpp @@ -4,6 +4,7 @@ #include "include/MPEG4Extractor.h" #include "media/stagefright/DataSource.h" +#include "media/stagefright/MediaDefs.h" #include "media/stagefright/MediaSource.h" #include "media/stagefright/MetaData.h" #include "mp4_demuxer/Adts.h" @@ -168,10 +169,12 @@ MP4Demuxer::DemuxAudioSample() } sample->Update(); - if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count, - mAudioConfig.frequency_index, - mAudioConfig.aac_profile, sample)) { - return nullptr; + if (!strcmp(mAudioConfig.mime_type, MEDIA_MIMETYPE_AUDIO_AAC)) { + if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count, + mAudioConfig.frequency_index, + mAudioConfig.aac_profile, sample)) { + return nullptr; + } } return sample.forget(); diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp index 93ac8e5cfe20..62811fbe0613 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp @@ -2293,10 +2293,7 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( if (objectTypeIndication == 0x6b) { // The media subtype is MP3 audio - // Our software MP3 audio decoder may not be able to handle - // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED - ALOGE("MP3 track in MP4/3GPP file is not supported"); - return ERROR_UNSUPPORTED; + mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); } const uint8_t *csd; From e7cb77616764fb47429d2eea784a465f65e0afe0 Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Thu, 14 Aug 2014 11:38:21 +0800 Subject: [PATCH 23/86] Bug 1033902 - Extract the logic of offload-audio from MediaOmxDecoder to a parent class. r=roc --HG-- rename : content/media/omx/MediaOmxDecoder.cpp => content/media/omx/MediaOmxCommonDecoder.cpp rename : content/media/omx/MediaOmxDecoder.h => content/media/omx/MediaOmxCommonDecoder.h rename : content/media/omx/MediaOmxReader.cpp => content/media/omx/MediaOmxCommonReader.cpp rename : content/media/omx/MediaOmxReader.h => content/media/omx/MediaOmxCommonReader.h --- content/media/MediaDecoder.h | 3 + content/media/omx/AudioOffloadPlayer.cpp | 10 +- content/media/omx/AudioOffloadPlayer.h | 26 +- content/media/omx/AudioOffloadPlayerBase.h | 4 +- content/media/omx/MediaCodecReader.cpp | 7 + content/media/omx/MediaCodecReader.h | 2 + content/media/omx/MediaOmxCommonDecoder.cpp | 254 ++++++++++++++++++++ content/media/omx/MediaOmxCommonDecoder.h | 62 +++++ content/media/omx/MediaOmxCommonReader.cpp | 81 +++++++ content/media/omx/MediaOmxCommonReader.h | 48 ++++ content/media/omx/MediaOmxDecoder.cpp | 220 ----------------- content/media/omx/MediaOmxDecoder.h | 44 +--- content/media/omx/MediaOmxReader.cpp | 45 +--- content/media/omx/MediaOmxReader.h | 23 +- content/media/omx/moz.build | 4 + 15 files changed, 492 insertions(+), 341 deletions(-) create mode 100644 content/media/omx/MediaOmxCommonDecoder.cpp create mode 100644 content/media/omx/MediaOmxCommonDecoder.h create mode 100644 content/media/omx/MediaOmxCommonReader.cpp create mode 100644 content/media/omx/MediaOmxCommonReader.h diff --git a/content/media/MediaDecoder.h b/content/media/MediaDecoder.h index 57577667e549..3a993651e956 100644 --- a/content/media/MediaDecoder.h +++ b/content/media/MediaDecoder.h @@ -758,6 +758,9 @@ public: MediaInfo* aInfo, MetadataTags* aTags); + int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; } + void ResetSeekTime() { mRequestedSeekTarget.Reset(); } + /****** * The following methods must only be called on the main * thread. diff --git a/content/media/omx/AudioOffloadPlayer.cpp b/content/media/omx/AudioOffloadPlayer.cpp index 1e1f354464b7..4379fb69160d 100755 --- a/content/media/omx/AudioOffloadPlayer.cpp +++ b/content/media/omx/AudioOffloadPlayer.cpp @@ -21,6 +21,7 @@ #include "nsComponentManagerUtils.h" #include "nsITimer.h" #include "mozilla/dom/HTMLMediaElement.h" +#include "VideoUtils.h" #include #include @@ -51,7 +52,7 @@ PRLogModuleInfo* gAudioOffloadPlayerLog; // When elapsed, the AudioSink is destroyed to allow the audio DSP to power down. static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll; -AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxDecoder* aObserver) : +AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxCommonDecoder* aObserver) : mObserver(aObserver), mInputBuffer(nullptr), mSampleRate(0), @@ -197,7 +198,8 @@ status_t AudioOffloadPlayer::ChangeState(MediaDecoder::PlayState aState) case MediaDecoder::PLAY_STATE_PAUSED: case MediaDecoder::PLAY_STATE_SHUTDOWN: // Just pause here during play state shutdown as well to stop playing - // offload track immediately. Resources will be freed by MediaOmxDecoder + // offload track immediately. Resources will be freed by + // MediaOmxCommonDecoder Pause(); break; @@ -421,14 +423,14 @@ void AudioOffloadPlayer::NotifyAudioEOS() void AudioOffloadPlayer::NotifyPositionChanged() { nsCOMPtr nsEvent = NS_NewRunnableMethod(mObserver, - &MediaOmxDecoder::PlaybackPositionChanged); + &MediaOmxCommonDecoder::PlaybackPositionChanged); NS_DispatchToMainThread(nsEvent); } void AudioOffloadPlayer::NotifyAudioTearDown() { nsCOMPtr nsEvent = NS_NewRunnableMethod(mObserver, - &MediaOmxDecoder::AudioOffloadTearDown); + &MediaOmxCommonDecoder::AudioOffloadTearDown); NS_DispatchToMainThread(nsEvent); } diff --git a/content/media/omx/AudioOffloadPlayer.h b/content/media/omx/AudioOffloadPlayer.h index 035ff8a00c7e..0d28bded1185 100755 --- a/content/media/omx/AudioOffloadPlayer.h +++ b/content/media/omx/AudioOffloadPlayer.h @@ -27,14 +27,12 @@ #include #include "AudioOutput.h" - +#include "AudioOffloadPlayerBase.h" #include "MediaDecoderOwner.h" -#include "MediaOmxDecoder.h" +#include "MediaOmxCommonDecoder.h" namespace mozilla { -class MediaOmxDecoder; - /** * AudioOffloadPlayer adds support for audio tunneling to a digital signal * processor (DSP) in the device chipset. With tunneling, audio decoding is @@ -47,11 +45,12 @@ class MediaOmxDecoder; * data, FillBuffer() will read data from compressed audio source and provide * it to the sink * - * Also this class passes state changes (play/pause/seek) from MediaOmxDecoder - * to AudioSink as well as provide AudioSink status (position changed, - * playback ended, seek complete, audio tear down) back to MediaOmxDecoder + * Also this class passes state changes (play/pause/seek) from + * MediaOmxCommonDecoder to AudioSink as well as provide AudioSink status + * (position changed, playback ended, seek complete, audio tear down) back to + * MediaOmxCommonDecoder * - * It acts as a bridge between MediaOmxDecoder and AudioSink during + * It acts as a bridge between MediaOmxCommonDecoder and AudioSink during * offload playback */ @@ -70,7 +69,7 @@ public: SEEK_COMPLETE }; - AudioOffloadPlayer(MediaOmxDecoder* aDecoder = nullptr); + AudioOffloadPlayer(MediaOmxCommonDecoder* aDecoder = nullptr); ~AudioOffloadPlayer(); @@ -146,7 +145,8 @@ private: // relative to the seeked position. And seeked position may be slightly // different than given mSeekTimeUs, if audio source cannot find a frame at // that position. Store seeked position in mStartPosUs and provide - // mStartPosUs + GetPosition() (i.e. absolute position) to MediaOmxDecoder + // mStartPosUs + GetPosition() (i.e. absolute position) to + // MediaOmxCommonDecoder // Used in main thread and offload callback thread, protected by Mutex // mLock int64_t mStartPosUs; @@ -161,7 +161,7 @@ private: // mLock int64_t mPositionTimeMediaUs; - // State obtained from MediaOmxDecoder. Used only in main thread + // State obtained from MediaOmxCommonDecoder. Used only in main thread MediaDecoder::PlayState mPlayState; // Protect accessing audio position related variables between main thread and @@ -180,8 +180,8 @@ private: // Buffer used to get date from audio source. Used in offload callback thread MediaBuffer* mInputBuffer; - // MediaOmxDecoder object used mainly to notify the audio sink status - MediaOmxDecoder* mObserver; + // MediaOmxCommonDecoder object used mainly to notify the audio sink status + MediaOmxCommonDecoder* mObserver; TimeStamp mLastFireUpdateTime; diff --git a/content/media/omx/AudioOffloadPlayerBase.h b/content/media/omx/AudioOffloadPlayerBase.h index a60e56622bd8..b332f8b0fce8 100644 --- a/content/media/omx/AudioOffloadPlayerBase.h +++ b/content/media/omx/AudioOffloadPlayerBase.h @@ -20,13 +20,11 @@ #ifndef AUDIO_OFFLOAD_PLAYER_BASE_H_ #define AUDIO_OFFLOAD_PLAYER_BASE_H_ +#include "MediaDecoder.h" #include "MediaDecoderOwner.h" -#include "MediaOmxDecoder.h" namespace mozilla { -class MediaOmxDecoder; - /** * AudioOffloadPlayer interface class which has funtions used by MediaOmxDecoder * This is to reduce the dependency of AudioOffloadPlayer in MediaOmxDecoder diff --git a/content/media/omx/MediaCodecReader.cpp b/content/media/omx/MediaCodecReader.cpp index 4ed087e1e863..97b67e704903 100644 --- a/content/media/omx/MediaCodecReader.cpp +++ b/content/media/omx/MediaCodecReader.cpp @@ -524,6 +524,13 @@ MediaCodecReader::IsMediaSeekable() return (mExtractor != nullptr) && (mExtractor->flags() & MediaExtractor::CAN_SEEK); } +android::sp +MediaCodecReader::GetAudioOffloadTrack() +{ + // TODO: return real track + return nullptr; +} + bool MediaCodecReader::ReallocateResources() { diff --git a/content/media/omx/MediaCodecReader.h b/content/media/omx/MediaCodecReader.h index 6ad8987f2aa5..a98f26a45ec7 100644 --- a/content/media/omx/MediaCodecReader.h +++ b/content/media/omx/MediaCodecReader.h @@ -85,6 +85,8 @@ public: virtual bool IsMediaSeekable() MOZ_OVERRIDE; + virtual android::sp GetAudioOffloadTrack(); + protected: struct TrackInputCopier { diff --git a/content/media/omx/MediaOmxCommonDecoder.cpp b/content/media/omx/MediaOmxCommonDecoder.cpp new file mode 100644 index 000000000000..43b8714b4fa0 --- /dev/null +++ b/content/media/omx/MediaOmxCommonDecoder.cpp @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "MediaOmxCommonDecoder.h" + +#include + +#include "AudioOffloadPlayerBase.h" +#include "MediaDecoderStateMachine.h" +#include "MediaOmxCommonReader.h" + +#ifdef MOZ_AUDIO_OFFLOAD +#include "AudioOffloadPlayer.h" +#endif + +using namespace android; + +namespace mozilla { + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gMediaDecoderLog; +#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg) +#else +#define DECODER_LOG(type, msg) +#endif + +MediaOmxCommonDecoder::MediaOmxCommonDecoder() + : MediaDecoder() + , mReader(nullptr) + , mCanOffloadAudio(false) + , mFallbackToStateMachine(false) +{ +#ifdef PR_LOGGING + if (!gMediaDecoderLog) { + gMediaDecoderLog = PR_NewLogModule("MediaDecoder"); + } +#endif +} + +void +MediaOmxCommonDecoder::SetCanOffloadAudio(bool aCanOffloadAudio) +{ + ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); + mCanOffloadAudio = aCanOffloadAudio; +} + +void +MediaOmxCommonDecoder::MetadataLoaded(MediaInfo* aInfo, + MetadataTags* aTags) +{ + MOZ_ASSERT(NS_IsMainThread()); + MediaDecoder::MetadataLoaded(aInfo, aTags); + + ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); + if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() || + mInitialPlaybackRate != 1.0) { + DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed", + __PRETTY_FUNCTION__)); + return; + } + +#ifdef MOZ_AUDIO_OFFLOAD + mAudioOffloadPlayer = new AudioOffloadPlayer(this); +#endif + if (!mAudioOffloadPlayer) { + return; + } + + mAudioOffloadPlayer->SetSource(mReader->GetAudioOffloadTrack()); + status_t err = mAudioOffloadPlayer->Start(false); + if (err == OK) { + PauseStateMachine(); + // Call ChangeState() to run AudioOffloadPlayer since offload state enabled + ChangeState(mPlayState); + return; + } + + mAudioOffloadPlayer = nullptr; + DECODER_LOG(PR_LOG_DEBUG, ("In %s Unable to start offload audio %d." + "Switching to normal mode", __PRETTY_FUNCTION__, err)); +} + +void +MediaOmxCommonDecoder::PauseStateMachine() +{ + MOZ_ASSERT(NS_IsMainThread()); + GetReentrantMonitor().AssertCurrentThreadIn(); + DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__)); + if (!mDecoderStateMachine) { + return; + } + StopProgress(); + mDecoderStateMachine->SetDormant(true); +} + +void +MediaOmxCommonDecoder::ResumeStateMachine() +{ + MOZ_ASSERT(NS_IsMainThread()); + ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); + DECODER_LOG(PR_LOG_DEBUG, ("%s current time %f", __PRETTY_FUNCTION__, + mCurrentTime)); + + if (!mDecoderStateMachine) { + return; + } + + mFallbackToStateMachine = true; + mAudioOffloadPlayer = nullptr; + int64_t timeUsecs = 0; + SecondsToUsecs(mCurrentTime, timeUsecs); + mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate); + + mNextState = mPlayState; + ChangeState(PLAY_STATE_LOADING); + mDecoderStateMachine->SetDormant(false); +} + +void +MediaOmxCommonDecoder::AudioOffloadTearDown() +{ + MOZ_ASSERT(NS_IsMainThread()); + DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__)); + + // mAudioOffloadPlayer can be null here if ResumeStateMachine was called + // just before because of some other error. + if (mAudioOffloadPlayer) { + // Audio offload player sent tear down event. Fallback to state machine + PlaybackPositionChanged(); + ResumeStateMachine(); + } +} + +void +MediaOmxCommonDecoder::AddOutputStream(ProcessedMediaStream* aStream, + bool aFinishWhenEnded) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mAudioOffloadPlayer) { + // Offload player cannot handle MediaStream. Fallback + PlaybackPositionChanged(); + ResumeStateMachine(); + } + + MediaDecoder::AddOutputStream(aStream, aFinishWhenEnded); +} + +void +MediaOmxCommonDecoder::SetPlaybackRate(double aPlaybackRate) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mAudioOffloadPlayer && + ((aPlaybackRate != 0.0) || (aPlaybackRate != 1.0))) { + // Offload player cannot handle playback rate other than 1/0. Fallback + PlaybackPositionChanged(); + ResumeStateMachine(); + } + + MediaDecoder::SetPlaybackRate(aPlaybackRate); +} + +void +MediaOmxCommonDecoder::ChangeState(PlayState aState) +{ + MOZ_ASSERT(NS_IsMainThread()); + // Keep MediaDecoder state in sync with MediaElement irrespective of offload + // playback so it will continue to work in normal mode when offloading fails + // in between + MediaDecoder::ChangeState(aState); + + if (mAudioOffloadPlayer) { + status_t err = mAudioOffloadPlayer->ChangeState(aState); + if (err != OK) { + ResumeStateMachine(); + } + } +} + +void +MediaOmxCommonDecoder::ApplyStateToStateMachine(PlayState aState) +{ + MOZ_ASSERT(NS_IsMainThread()); + // During offload playback, state machine should be in dormant state. + // ApplyStateToStateMachine() can change state machine state to + // something else or reset the seek time. So don't call this when audio is + // offloaded + if (!mAudioOffloadPlayer) { + MediaDecoder::ApplyStateToStateMachine(aState); + } +} + +void +MediaOmxCommonDecoder::PlaybackPositionChanged() +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!mAudioOffloadPlayer) { + MediaDecoder::PlaybackPositionChanged(); + return; + } + + if (!mOwner || mShuttingDown) { + return; + } + + double lastTime = mCurrentTime; + { + ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); + mCurrentTime = mAudioOffloadPlayer->GetMediaTimeSecs(); + } + if (mOwner && lastTime != mCurrentTime) { + FireTimeUpdate(); + } +} + +void +MediaOmxCommonDecoder::SetElementVisibility(bool aIsVisible) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (mAudioOffloadPlayer) { + mAudioOffloadPlayer->SetElementVisibility(aIsVisible); + } +} + +void +MediaOmxCommonDecoder::UpdateReadyStateForData() +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!mAudioOffloadPlayer) { + MediaDecoder::UpdateReadyStateForData(); + return; + } + + if (!mOwner || mShuttingDown) + return; + mOwner->UpdateReadyStateForData(mAudioOffloadPlayer->GetNextFrameStatus()); +} + +void +MediaOmxCommonDecoder::SetVolume(double aVolume) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!mAudioOffloadPlayer) { + MediaDecoder::SetVolume(aVolume); + return; + } + mAudioOffloadPlayer->SetVolume(aVolume); +} + +} // namespace mozilla diff --git a/content/media/omx/MediaOmxCommonDecoder.h b/content/media/omx/MediaOmxCommonDecoder.h new file mode 100644 index 000000000000..50a6bca41371 --- /dev/null +++ b/content/media/omx/MediaOmxCommonDecoder.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 MEDIA_OMX_COMMON_DECODER_H +#define MEDIA_OMX_COMMON_DECODER_H + +#include "MediaDecoder.h" + +namespace android { +struct MOZ_EXPORT MediaSource; +} // namespace android + +namespace mozilla { + +class AudioOffloadPlayerBase; +class MediaOmxCommonReader; + +class MediaOmxCommonDecoder : public MediaDecoder +{ +public: + MediaOmxCommonDecoder(); + + virtual void MetadataLoaded(MediaInfo* aInfo, + MetadataTags* aTags); + virtual void ChangeState(PlayState aState); + virtual void ApplyStateToStateMachine(PlayState aState); + virtual void SetVolume(double aVolume); + virtual void PlaybackPositionChanged(); + virtual void UpdateReadyStateForData(); + virtual void SetElementVisibility(bool aIsVisible); + virtual void SetCanOffloadAudio(bool aCanOffloadAudio); + virtual void AddOutputStream(ProcessedMediaStream* aStream, + bool aFinishWhenEnded); + virtual void SetPlaybackRate(double aPlaybackRate); + + void AudioOffloadTearDown(); + +protected: + void PauseStateMachine(); + void ResumeStateMachine(); + + MediaOmxCommonReader* mReader; + + // Offloaded audio track + android::sp mAudioTrack; + + nsAutoPtr mAudioOffloadPlayer; + + // Set by Media*Reader to denote current track can be offloaded + bool mCanOffloadAudio; + + // Set when offload playback of current track fails in the middle and need to + // fallback to state machine + bool mFallbackToStateMachine; +}; + +} // namespace mozilla + +#endif // MEDIA_OMX_COMMON_DECODER_H diff --git a/content/media/omx/MediaOmxCommonReader.cpp b/content/media/omx/MediaOmxCommonReader.cpp new file mode 100644 index 000000000000..4af94c2ff063 --- /dev/null +++ b/content/media/omx/MediaOmxCommonReader.cpp @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "MediaOmxCommonReader.h" + +#include + +#include "AbstractMediaDecoder.h" +#include "AudioChannelService.h" +#include "MediaStreamSource.h" + +#ifdef MOZ_AUDIO_OFFLOAD +#include +#include +#include +#endif + +using namespace android; + +namespace mozilla { + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gMediaDecoderLog; +#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg) +#else +#define DECODER_LOG(type, msg) +#endif + +MediaOmxCommonReader::MediaOmxCommonReader(AbstractMediaDecoder *aDecoder) + : MediaDecoderReader(aDecoder) +{ +#ifdef PR_LOGGING + if (!gMediaDecoderLog) { + gMediaDecoderLog = PR_NewLogModule("MediaDecoder"); + } +#endif + + mAudioChannel = dom::AudioChannelService::GetDefaultAudioChannel(); +} + +#ifdef MOZ_AUDIO_OFFLOAD +void MediaOmxCommonReader::CheckAudioOffload() +{ + NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); + + char offloadProp[128]; + property_get("audio.offload.disable", offloadProp, "0"); + bool offloadDisable = atoi(offloadProp) != 0; + if (offloadDisable) { + return; + } + + sp audioOffloadTrack = GetAudioOffloadTrack(); + sp meta = audioOffloadTrack.get() + ? audioOffloadTrack->getFormat() : nullptr; + + // Supporting audio offload only when there is no video, no streaming + bool hasNoVideo = !HasVideo(); + bool isNotStreaming + = mDecoder->GetResource()->IsDataCachedToEndOfResource(0); + + // Not much benefit in trying to offload other channel types. Most of them + // aren't supported and also duration would be less than a minute + bool isTypeMusic = mAudioChannel == dom::AudioChannel::Content; + + DECODER_LOG(PR_LOG_DEBUG, ("%s meta %p, no video %d, no streaming %d," + " channel type %d", __FUNCTION__, meta.get(), hasNoVideo, + isNotStreaming, mAudioChannel)); + + if ((meta.get()) && hasNoVideo && isNotStreaming && isTypeMusic && + canOffloadStream(meta, false, false, AUDIO_STREAM_MUSIC)) { + DECODER_LOG(PR_LOG_DEBUG, ("Can offload this audio stream")); + mDecoder->SetCanOffloadAudio(true); + } +} +#endif + +} // namespace mozilla diff --git a/content/media/omx/MediaOmxCommonReader.h b/content/media/omx/MediaOmxCommonReader.h new file mode 100644 index 000000000000..8f5984955bc9 --- /dev/null +++ b/content/media/omx/MediaOmxCommonReader.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 MEDIA_OMX_COMMON_READER_H +#define MEDIA_OMX_COMMON_READER_H + +#include "MediaDecoderReader.h" + +#include + +#include "mozilla/dom/AudioChannelBinding.h" + +namespace android { +struct MOZ_EXPORT MediaSource; +} // namespace android + +namespace mozilla { + +class AbstractMediaDecoder; + +class MediaOmxCommonReader : public MediaDecoderReader +{ +public: + MediaOmxCommonReader(AbstractMediaDecoder* aDecoder); + + void SetAudioChannel(dom::AudioChannel aAudioChannel) { + mAudioChannel = aAudioChannel; + } + + virtual android::sp GetAudioOffloadTrack() = 0; + +#ifdef MOZ_AUDIO_OFFLOAD + // Check whether it is possible to offload current audio track. This access + // canOffloadStream() from libStageFright Utils.cpp, which is not there in + // ANDROID_VERSION < 19 + void CheckAudioOffload(); +#endif + +protected: + dom::AudioChannel mAudioChannel; +}; + +} // namespace mozilla + +#endif // MEDIA_OMX_COMMON_READER_H diff --git a/content/media/omx/MediaOmxDecoder.cpp b/content/media/omx/MediaOmxDecoder.cpp index 2a27de816686..e4aad765ea6d 100755 --- a/content/media/omx/MediaOmxDecoder.cpp +++ b/content/media/omx/MediaOmxDecoder.cpp @@ -7,37 +7,11 @@ #include "MediaOmxDecoder.h" #include "MediaOmxReader.h" #include "MediaDecoderStateMachine.h" -#include "VideoUtils.h" - -#include "OmxDecoder.h" - -#ifdef MOZ_AUDIO_OFFLOAD -#include "AudioOffloadPlayer.h" -#endif using namespace android; namespace mozilla { -#ifdef PR_LOGGING -extern PRLogModuleInfo* gMediaDecoderLog; -#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg) -#else -#define DECODER_LOG(type, msg) -#endif - -MediaOmxDecoder::MediaOmxDecoder() : - MediaDecoder(), - mCanOffloadAudio(false), - mFallbackToStateMachine(false) -{ -#ifdef PR_LOGGING - if (!gMediaDecoderLog) { - gMediaDecoderLog = PR_NewLogModule("MediaDecoder"); - } -#endif -} - MediaDecoder* MediaOmxDecoder::Clone() { return new MediaOmxDecoder(); @@ -50,198 +24,4 @@ MediaDecoderStateMachine* MediaOmxDecoder::CreateStateMachine() return new MediaDecoderStateMachine(this, mReader); } -void MediaOmxDecoder::SetCanOffloadAudio(bool aCanOffloadAudio) -{ - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - mCanOffloadAudio = aCanOffloadAudio; -} - -void MediaOmxDecoder::MetadataLoaded(MediaInfo* aInfo, - MetadataTags* aTags) -{ - MOZ_ASSERT(NS_IsMainThread()); - MediaDecoder::MetadataLoaded(aInfo, aTags); - - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() || - mInitialPlaybackRate != 1.0) { - DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed", - __PRETTY_FUNCTION__)); - return; - } - -#ifdef MOZ_AUDIO_OFFLOAD - mAudioOffloadPlayer = new AudioOffloadPlayer(this); -#endif - mAudioOffloadPlayer->SetSource(mReader->GetAudioOffloadTrack()); - status_t err = mAudioOffloadPlayer->Start(false); - if (err == OK) { - PauseStateMachine(); - // Call ChangeState() to run AudioOffloadPlayer since offload state enabled - ChangeState(mPlayState); - return; - } - - mAudioOffloadPlayer = nullptr; - DECODER_LOG(PR_LOG_DEBUG, ("In %s Unable to start offload audio %d." - "Switching to normal mode", __PRETTY_FUNCTION__, err)); -} - -void MediaOmxDecoder::PauseStateMachine() -{ - MOZ_ASSERT(NS_IsMainThread()); - GetReentrantMonitor().AssertCurrentThreadIn(); - DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__)); - if (!mDecoderStateMachine) { - return; - } - StopProgress(); - mDecoderStateMachine->SetDormant(true); -} - -void MediaOmxDecoder::ResumeStateMachine() -{ - MOZ_ASSERT(NS_IsMainThread()); - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - DECODER_LOG(PR_LOG_DEBUG, ("%s current time %f", __PRETTY_FUNCTION__, - mCurrentTime)); - - if (!mDecoderStateMachine) { - return; - } - - mFallbackToStateMachine = true; - mAudioOffloadPlayer = nullptr; - int64_t timeUsecs = 0; - SecondsToUsecs(mCurrentTime, timeUsecs); - mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate); - - mNextState = mPlayState; - ChangeState(PLAY_STATE_LOADING); - mDecoderStateMachine->SetDormant(false); -} - -void MediaOmxDecoder::AudioOffloadTearDown() -{ - MOZ_ASSERT(NS_IsMainThread()); - DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__)); - - // mAudioOffloadPlayer can be null here if ResumeStateMachine was called - // just before because of some other error. - if (mAudioOffloadPlayer) { - // Audio offload player sent tear down event. Fallback to state machine - PlaybackPositionChanged(); - ResumeStateMachine(); - } -} - -void MediaOmxDecoder::AddOutputStream(ProcessedMediaStream* aStream, - bool aFinishWhenEnded) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (mAudioOffloadPlayer) { - // Offload player cannot handle MediaStream. Fallback - PlaybackPositionChanged(); - ResumeStateMachine(); - } - - MediaDecoder::AddOutputStream(aStream, aFinishWhenEnded); -} - -void MediaOmxDecoder::SetPlaybackRate(double aPlaybackRate) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (mAudioOffloadPlayer && - ((aPlaybackRate != 0.0) || (aPlaybackRate != 1.0))) { - // Offload player cannot handle playback rate other than 1/0. Fallback - PlaybackPositionChanged(); - ResumeStateMachine(); - } - - MediaDecoder::SetPlaybackRate(aPlaybackRate); -} - -void MediaOmxDecoder::ChangeState(PlayState aState) -{ - MOZ_ASSERT(NS_IsMainThread()); - // Keep MediaDecoder state in sync with MediaElement irrespective of offload - // playback so it will continue to work in normal mode when offloading fails - // in between - MediaDecoder::ChangeState(aState); - - if (mAudioOffloadPlayer) { - status_t err = mAudioOffloadPlayer->ChangeState(aState); - if (err != OK) { - ResumeStateMachine(); - } - } -} - -void MediaOmxDecoder::ApplyStateToStateMachine(PlayState aState) -{ - MOZ_ASSERT(NS_IsMainThread()); - // During offload playback, state machine should be in dormant state. - // ApplyStateToStateMachine() can change state machine state to - // something else or reset the seek time. So don't call this when audio is - // offloaded - if (!mAudioOffloadPlayer) { - MediaDecoder::ApplyStateToStateMachine(aState); - } -} - -void MediaOmxDecoder::PlaybackPositionChanged() -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!mAudioOffloadPlayer) { - MediaDecoder::PlaybackPositionChanged(); - return; - } - - if (!mOwner || mShuttingDown) { - return; - } - - double lastTime = mCurrentTime; - { - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - mCurrentTime = mAudioOffloadPlayer->GetMediaTimeSecs(); - } - if (mOwner && lastTime != mCurrentTime) { - FireTimeUpdate(); - } -} - -void MediaOmxDecoder::SetElementVisibility(bool aIsVisible) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mAudioOffloadPlayer) { - mAudioOffloadPlayer->SetElementVisibility(aIsVisible); - } -} - -void MediaOmxDecoder::UpdateReadyStateForData() -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!mAudioOffloadPlayer) { - MediaDecoder::UpdateReadyStateForData(); - return; - } - - if (!mOwner || mShuttingDown) - return; - mOwner->UpdateReadyStateForData(mAudioOffloadPlayer->GetNextFrameStatus()); -} - -void MediaOmxDecoder::SetVolume(double aVolume) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!mAudioOffloadPlayer) { - MediaDecoder::SetVolume(aVolume); - return; - } - mAudioOffloadPlayer->SetVolume(aVolume); -} - } // namespace mozilla diff --git a/content/media/omx/MediaOmxDecoder.h b/content/media/omx/MediaOmxDecoder.h index 5d1850745099..90f13c7e3ccd 100755 --- a/content/media/omx/MediaOmxDecoder.h +++ b/content/media/omx/MediaOmxDecoder.h @@ -6,55 +6,15 @@ #if !defined(MediaOmxDecoder_h_) #define MediaOmxDecoder_h_ -#include "base/basictypes.h" -#include "MediaDecoder.h" -#include "MediaOmxReader.h" -#include "AudioOffloadPlayerBase.h" +#include "MediaOmxCommonDecoder.h" namespace mozilla { -class MediaOmxDecoder : public MediaDecoder +class MediaOmxDecoder : public MediaOmxCommonDecoder { - typedef android::MediaSource MediaSource; public: - MediaOmxDecoder(); virtual MediaDecoder* Clone(); virtual MediaDecoderStateMachine* CreateStateMachine(); - - virtual void MetadataLoaded(MediaInfo* aInfo, - MetadataTags* aTags); - virtual void ChangeState(PlayState aState); - virtual void ApplyStateToStateMachine(PlayState aState); - virtual void SetVolume(double aVolume); - virtual void PlaybackPositionChanged(); - virtual void UpdateReadyStateForData(); - virtual void SetElementVisibility(bool aIsVisible); - virtual void SetCanOffloadAudio(bool aCanOffloadAudio); - virtual void AddOutputStream(ProcessedMediaStream* aStream, - bool aFinishWhenEnded); - virtual void SetPlaybackRate(double aPlaybackRate); - - void AudioOffloadTearDown(); - int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; } - void ResetSeekTime() { mRequestedSeekTarget.Reset(); } - -private: - void PauseStateMachine(); - void ResumeStateMachine(); - - MediaOmxReader* mReader; - - // Offloaded audio track - android::sp mAudioTrack; - - nsAutoPtr mAudioOffloadPlayer; - - // Set by MediaOmxReader to denote current track can be offloaded - bool mCanOffloadAudio; - - // Set when offload playback of current track fails in the middle and need to - // fallback to state machine - bool mFallbackToStateMachine; }; } // namespace mozilla diff --git a/content/media/omx/MediaOmxReader.cpp b/content/media/omx/MediaOmxReader.cpp index 6844054f4861..e4ec2c533346 100644 --- a/content/media/omx/MediaOmxReader.cpp +++ b/content/media/omx/MediaOmxReader.cpp @@ -19,12 +19,6 @@ #include "gfx2DGlue.h" #include "MediaStreamSource.h" -#ifdef MOZ_AUDIO_OFFLOAD -#include -#include -#include -#endif - #define MAX_DROPPED_FRAMES 25 // Try not to spend more than this much time in a single call to DecodeVideoFrame. #define MAX_VIDEO_DECODE_SECONDS 0.1 @@ -42,7 +36,7 @@ extern PRLogModuleInfo* gMediaDecoderLog; #endif MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder) - : MediaDecoderReader(aDecoder) + : MediaOmxCommonReader(aDecoder) , mHasVideo(false) , mHasAudio(false) , mVideoSeekTimeUs(-1) @@ -425,41 +419,12 @@ void MediaOmxReader::EnsureActive() { NS_ASSERTION(result == NS_OK, "OmxDecoder should be in play state to continue decoding"); } -#ifdef MOZ_AUDIO_OFFLOAD -void MediaOmxReader::CheckAudioOffload() +android::sp MediaOmxReader::GetAudioOffloadTrack() { - NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); - - char offloadProp[128]; - property_get("audio.offload.disable", offloadProp, "0"); - bool offloadDisable = atoi(offloadProp) != 0; - if (offloadDisable) { - return; - } - - mAudioOffloadTrack = mOmxDecoder->GetAudioOffloadTrack(); - sp meta = (mAudioOffloadTrack.get()) ? - mAudioOffloadTrack->getFormat() : nullptr; - - // Supporting audio offload only when there is no video, no streaming - bool hasNoVideo = !mOmxDecoder->HasVideo(); - bool isNotStreaming - = mDecoder->GetResource()->IsDataCachedToEndOfResource(0); - - // Not much benefit in trying to offload other channel types. Most of them - // aren't supported and also duration would be less than a minute - bool isTypeMusic = mAudioChannel == dom::AudioChannel::Content; - - DECODER_LOG(PR_LOG_DEBUG, ("%s meta %p, no video %d, no streaming %d," - " channel type %d", __FUNCTION__, meta.get(), hasNoVideo, - isNotStreaming, mAudioChannel)); - - if ((meta.get()) && hasNoVideo && isNotStreaming && isTypeMusic && - canOffloadStream(meta, false, false, AUDIO_STREAM_MUSIC)) { - DECODER_LOG(PR_LOG_DEBUG, ("Can offload this audio stream")); - mDecoder->SetCanOffloadAudio(true); + if (!mOmxDecoder.get()) { + return nullptr; } + return mOmxDecoder->GetAudioOffloadTrack(); } -#endif } // namespace mozilla diff --git a/content/media/omx/MediaOmxReader.h b/content/media/omx/MediaOmxReader.h index 839e04c7c163..4627f6912387 100644 --- a/content/media/omx/MediaOmxReader.h +++ b/content/media/omx/MediaOmxReader.h @@ -6,10 +6,10 @@ #if !defined(MediaOmxReader_h_) #define MediaOmxReader_h_ +#include "MediaOmxCommonReader.h" #include "MediaResource.h" #include "MediaDecoderReader.h" #include "nsRect.h" -#include "mozilla/dom/AudioChannelBinding.h" #include #include @@ -26,7 +26,7 @@ namespace dom { class AbstractMediaDecoder; -class MediaOmxReader : public MediaDecoderReader +class MediaOmxReader : public MediaOmxCommonReader { nsCString mType; bool mHasVideo; @@ -36,8 +36,6 @@ class MediaOmxReader : public MediaDecoderReader int64_t mVideoSeekTimeUs; int64_t mAudioSeekTimeUs; int32_t mSkipCount; - dom::AudioChannel mAudioChannel; - android::sp mAudioOffloadTrack; protected: android::sp mOmxDecoder; @@ -90,22 +88,9 @@ public: virtual void Shutdown() MOZ_OVERRIDE; - void SetAudioChannel(dom::AudioChannel aAudioChannel) { - mAudioChannel = aAudioChannel; - } - - android::sp GetAudioOffloadTrack() { - return mAudioOffloadTrack; - } - -#ifdef MOZ_AUDIO_OFFLOAD - // Check whether it is possible to offload current audio track. This access - // canOffloadStream() from libStageFright Utils.cpp, which is not there in - // ANDROID_VERSION < 19 - void CheckAudioOffload(); -#endif - void ReleaseDecoder(); + + android::sp GetAudioOffloadTrack(); }; } // namespace mozilla diff --git a/content/media/omx/moz.build b/content/media/omx/moz.build index 922f264c719d..306fbe747b88 100644 --- a/content/media/omx/moz.build +++ b/content/media/omx/moz.build @@ -6,11 +6,15 @@ EXPORTS += [ 'AudioOffloadPlayerBase.h', + 'MediaOmxCommonDecoder.h', + 'MediaOmxCommonReader.h', 'MediaOmxDecoder.h', 'MediaOmxReader.h', ] SOURCES += [ + 'MediaOmxCommonDecoder.cpp', + 'MediaOmxCommonReader.cpp', 'MediaOmxDecoder.cpp', 'MediaOmxReader.cpp', 'MediaStreamSource.cpp', From 25eb5dd651dcb78a264273349db41047c80cc50f Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Thu, 14 Aug 2014 11:40:20 +0800 Subject: [PATCH 24/86] Bug 1033902 - Integrate offload player into MediaCodec related codes. r=roc --- content/media/omx/AudioOffloadPlayer.cpp | 0 content/media/omx/AudioOffloadPlayer.h | 0 content/media/omx/MediaCodecDecoder.cpp | 15 ++++++++++++--- content/media/omx/MediaCodecDecoder.h | 8 +++++--- content/media/omx/MediaCodecReader.cpp | 20 +++++++++++++------- content/media/omx/MediaCodecReader.h | 7 ++++--- content/media/omx/MediaOmxCommonDecoder.cpp | 10 ++++++++++ content/media/omx/MediaOmxCommonDecoder.h | 5 +++++ content/media/omx/MediaOmxDecoder.cpp | 16 +++++++++++----- content/media/omx/MediaOmxDecoder.h | 3 ++- 10 files changed, 62 insertions(+), 22 deletions(-) mode change 100755 => 100644 content/media/omx/AudioOffloadPlayer.cpp mode change 100755 => 100644 content/media/omx/AudioOffloadPlayer.h mode change 100755 => 100644 content/media/omx/MediaOmxDecoder.cpp mode change 100755 => 100644 content/media/omx/MediaOmxDecoder.h diff --git a/content/media/omx/AudioOffloadPlayer.cpp b/content/media/omx/AudioOffloadPlayer.cpp old mode 100755 new mode 100644 diff --git a/content/media/omx/AudioOffloadPlayer.h b/content/media/omx/AudioOffloadPlayer.h old mode 100755 new mode 100644 diff --git a/content/media/omx/MediaCodecDecoder.cpp b/content/media/omx/MediaCodecDecoder.cpp index ff5d90ee638d..427c2df815ba 100644 --- a/content/media/omx/MediaCodecDecoder.cpp +++ b/content/media/omx/MediaCodecDecoder.cpp @@ -5,6 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MediaCodecDecoder.h" + +#include + #include "MediaCodecReader.h" #include "MediaDecoderStateMachine.h" @@ -16,10 +19,16 @@ MediaCodecDecoder::Clone() return new MediaCodecDecoder(); } -MediaDecoderStateMachine* -MediaCodecDecoder::CreateStateMachine() +MediaOmxCommonReader* +MediaCodecDecoder::CreateReader() { - return new MediaDecoderStateMachine(this, new MediaCodecReader(this)); + return new MediaCodecReader(this); +} + +MediaDecoderStateMachine* +MediaCodecDecoder::CreateStateMachine(MediaOmxCommonReader* aReader) +{ + return new MediaDecoderStateMachine(this, aReader); } } // namespace mozilla diff --git a/content/media/omx/MediaCodecDecoder.h b/content/media/omx/MediaCodecDecoder.h index 4323ed2eda5b..95f659552973 100644 --- a/content/media/omx/MediaCodecDecoder.h +++ b/content/media/omx/MediaCodecDecoder.h @@ -7,18 +7,20 @@ #ifndef MEDIA_CODEC_DECODER_H #define MEDIA_CODEC_DECODER_H -#include "MediaDecoder.h" +#include "MediaOmxCommonDecoder.h" namespace mozilla { // MediaDecoder that uses MediaCodecReader. -class MediaCodecDecoder : public MediaDecoder +class MediaCodecDecoder : public MediaOmxCommonDecoder { public: virtual MediaDecoder* Clone(); - virtual MediaDecoderStateMachine* CreateStateMachine(); + virtual MediaOmxCommonReader* CreateReader(); + + virtual MediaDecoderStateMachine* CreateStateMachine(MediaOmxCommonReader* aReader); }; } // namespace mozilla diff --git a/content/media/omx/MediaCodecReader.cpp b/content/media/omx/MediaCodecReader.cpp index 97b67e704903..2ada812ac406 100644 --- a/content/media/omx/MediaCodecReader.cpp +++ b/content/media/omx/MediaCodecReader.cpp @@ -106,7 +106,8 @@ MediaCodecReader::VideoResourceListener::codecCanceled() } } -bool MediaCodecReader::TrackInputCopier::Copy(MediaBuffer* aSourceBuffer, sp aCodecBuffer) +bool +MediaCodecReader::TrackInputCopier::Copy(MediaBuffer* aSourceBuffer, sp aCodecBuffer) { if (aSourceBuffer == nullptr || aCodecBuffer == nullptr || @@ -132,7 +133,8 @@ MediaCodecReader::Track::Track() // Append the value of |kKeyValidSamples| to the end of each vorbis buffer. // https://github.com/mozilla-b2g/platform_frameworks_av/blob/master/media/libstagefright/OMXCodec.cpp#L3128 // https://github.com/mozilla-b2g/platform_frameworks_av/blob/master/media/libstagefright/NuMediaExtractor.cpp#L472 -bool MediaCodecReader::VorbisInputCopier::Copy(MediaBuffer* aSourceBuffer, sp aCodecBuffer) +bool +MediaCodecReader::VorbisInputCopier::Copy(MediaBuffer* aSourceBuffer, sp aCodecBuffer) { if (aSourceBuffer == nullptr || aCodecBuffer == nullptr || @@ -176,7 +178,7 @@ MediaCodecReader::CodecBufferInfo::CodecBufferInfo() } MediaCodecReader::MediaCodecReader(AbstractMediaDecoder* aDecoder) - : MediaDecoderReader(aDecoder) + : MediaOmxCommonReader(aDecoder) , mColorConverterBufferSize(0) { mHandler = new MessageHandler(this); @@ -427,6 +429,10 @@ MediaCodecReader::ReadMetadata(MediaInfo* aInfo, return NS_ERROR_FAILURE; } +#ifdef MOZ_AUDIO_OFFLOAD + CheckAudioOffload(); +#endif + if (IsWaitingMediaResources()) { return NS_OK; } @@ -527,8 +533,7 @@ MediaCodecReader::IsMediaSeekable() android::sp MediaCodecReader::GetAudioOffloadTrack() { - // TODO: return real track - return nullptr; + return mAudioOffloadTrack.mSource; } bool @@ -682,6 +687,8 @@ MediaCodecReader::CreateMediaSources() if (audioSource != nullptr && audioSource->start() == OK) { mAudioTrack.mSource = audioSource; } + // Get one another track instance for audio offload playback. + mAudioOffloadTrack.mSource = mExtractor->getTrack(audioTrackIndex); } if (videoTrackIndex != invalidTrackIndex && mVideoTrack.mSource == nullptr) { @@ -701,6 +708,7 @@ MediaCodecReader::DestroyMediaSources() { mAudioTrack.mSource = nullptr; mVideoTrack.mSource = nullptr; + mAudioOffloadTrack.mSource = nullptr; } bool @@ -1234,8 +1242,6 @@ MediaCodecReader::onMessageReceived(const sp &aMessage) break; } - // TODO - default: TRESPASS(); break; diff --git a/content/media/omx/MediaCodecReader.h b/content/media/omx/MediaCodecReader.h index a98f26a45ec7..06cd0a554eff 100644 --- a/content/media/omx/MediaCodecReader.h +++ b/content/media/omx/MediaCodecReader.h @@ -15,7 +15,7 @@ #include "I420ColorConverterHelper.h" #include "MediaCodecProxy.h" -#include "MediaDecoderReader.h" +#include "MediaOmxCommonReader.h" namespace android { struct ALooper; @@ -29,7 +29,7 @@ struct MediaCodec; namespace mozilla { -class MediaCodecReader : public MediaDecoderReader +class MediaCodecReader : public MediaOmxCommonReader { public: MediaCodecReader(AbstractMediaDecoder* aDecoder); @@ -251,9 +251,10 @@ private: android::sp mLooper; android::sp mExtractor; - // media elements + // media tracks AudioTrack mAudioTrack; VideoTrack mVideoTrack; + AudioTrack mAudioOffloadTrack; // only Track::mSource is valid // color converter android::I420ColorConverterHelper mColorConverter; diff --git a/content/media/omx/MediaOmxCommonDecoder.cpp b/content/media/omx/MediaOmxCommonDecoder.cpp index 43b8714b4fa0..9d43832918f2 100644 --- a/content/media/omx/MediaOmxCommonDecoder.cpp +++ b/content/media/omx/MediaOmxCommonDecoder.cpp @@ -251,4 +251,14 @@ MediaOmxCommonDecoder::SetVolume(double aVolume) mAudioOffloadPlayer->SetVolume(aVolume); } +MediaDecoderStateMachine* +MediaOmxCommonDecoder::CreateStateMachine() +{ + mReader = CreateReader(); + if (mReader != nullptr) { + mReader->SetAudioChannel(GetAudioChannel()); + } + return CreateStateMachine(mReader); +} + } // namespace mozilla diff --git a/content/media/omx/MediaOmxCommonDecoder.h b/content/media/omx/MediaOmxCommonDecoder.h index 50a6bca41371..5fe2e2fd5ee9 100644 --- a/content/media/omx/MediaOmxCommonDecoder.h +++ b/content/media/omx/MediaOmxCommonDecoder.h @@ -38,6 +38,11 @@ public: void AudioOffloadTearDown(); + virtual MediaDecoderStateMachine* CreateStateMachine(); + + virtual MediaOmxCommonReader* CreateReader() = 0; + virtual MediaDecoderStateMachine* CreateStateMachine(MediaOmxCommonReader* aReader) = 0; + protected: void PauseStateMachine(); void ResumeStateMachine(); diff --git a/content/media/omx/MediaOmxDecoder.cpp b/content/media/omx/MediaOmxDecoder.cpp old mode 100755 new mode 100644 index e4aad765ea6d..e4ec6bf2740a --- a/content/media/omx/MediaOmxDecoder.cpp +++ b/content/media/omx/MediaOmxDecoder.cpp @@ -12,16 +12,22 @@ using namespace android; namespace mozilla { -MediaDecoder* MediaOmxDecoder::Clone() +MediaDecoder* +MediaOmxDecoder::Clone() { return new MediaOmxDecoder(); } -MediaDecoderStateMachine* MediaOmxDecoder::CreateStateMachine() +MediaOmxCommonReader* +MediaOmxDecoder::CreateReader() { - mReader = new MediaOmxReader(this); - mReader->SetAudioChannel(GetAudioChannel()); - return new MediaDecoderStateMachine(this, mReader); + return new MediaOmxReader(this); +} + +MediaDecoderStateMachine* +MediaOmxDecoder::CreateStateMachine(MediaOmxCommonReader* aReader) +{ + return new MediaDecoderStateMachine(this, aReader); } } // namespace mozilla diff --git a/content/media/omx/MediaOmxDecoder.h b/content/media/omx/MediaOmxDecoder.h old mode 100755 new mode 100644 index 90f13c7e3ccd..95b6ea37ffaf --- a/content/media/omx/MediaOmxDecoder.h +++ b/content/media/omx/MediaOmxDecoder.h @@ -14,7 +14,8 @@ class MediaOmxDecoder : public MediaOmxCommonDecoder { public: virtual MediaDecoder* Clone(); - virtual MediaDecoderStateMachine* CreateStateMachine(); + virtual MediaOmxCommonReader* CreateReader(); + virtual MediaDecoderStateMachine* CreateStateMachine(MediaOmxCommonReader* aReader); }; } // namespace mozilla From 7da0afd3c8bd7a345fa8b1b4d65d7fdbb5f35ab0 Mon Sep 17 00:00:00 2001 From: Dragana Damjanovic Date: Wed, 13 Aug 2014 10:52:00 -0400 Subject: [PATCH 25/86] Bug 1043256 - If unKnownDecoder needs to be used, Content_Encodings will be loaded before OnStartRequest is called on the listener. This makes an error in e10s because Content_Encodings will be loaded before HttpChannelParent can disable them. r=bagder --- netwerk/base/public/nsIEncodedChannel.idl | 11 ++ netwerk/protocol/http/HttpBaseChannel.cpp | 19 +- netwerk/protocol/http/HttpBaseChannel.h | 4 +- netwerk/protocol/http/HttpChannelChild.cpp | 9 +- netwerk/protocol/http/nsHttpChannel.cpp | 23 ++- .../converters/nsUnknownDecoder.cpp | 177 ++++++++++++++++-- .../streamconv/converters/nsUnknownDecoder.h | 24 +++ .../unit/test_reply_without_content_type.js | 61 ++++-- 8 files changed, 283 insertions(+), 45 deletions(-) diff --git a/netwerk/base/public/nsIEncodedChannel.idl b/netwerk/base/public/nsIEncodedChannel.idl index b228556637fe..6ff465a155c6 100644 --- a/netwerk/base/public/nsIEncodedChannel.idl +++ b/netwerk/base/public/nsIEncodedChannel.idl @@ -6,6 +6,9 @@ #include "nsISupports.idl" interface nsIUTF8StringEnumerator; +interface nsIStreamListener; +interface nsISupports; + /** * A channel interface which allows special handling of encoded content */ @@ -41,4 +44,12 @@ interface nsIEncodedChannel : nsISupports * TRUE by default. */ attribute boolean applyConversion; + + /** + * This function will start converters if they are available. + * aNewNextListener will be nullptr if no converter is available. + */ + void doApplyContentConversions(in nsIStreamListener aNextListener, + out nsIStreamListener aNewNextListener, + in nsISupports aCtxt); }; diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 97790ec4ec93..24fae1ca27ee 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -604,13 +604,17 @@ HttpBaseChannel::SetApplyConversion(bool value) return NS_OK; } -nsresult -HttpBaseChannel::ApplyContentConversions() +NS_IMETHODIMP +HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener, + nsIStreamListener** aNewNextListener, + nsISupports *aCtxt) { + *aNewNextListener = nullptr; + nsCOMPtr nextListener = aNextListener; if (!mResponseHead) return NS_OK; - LOG(("HttpBaseChannel::ApplyContentConversions [this=%p]\n", this)); + LOG(("HttpBaseChannel::DoApplyContentConversions [this=%p]\n", this)); if (!mApplyConversion) { LOG(("not applying conversion per mApplyConversion\n")); @@ -659,8 +663,8 @@ HttpBaseChannel::ApplyContentConversions() ToLowerCase(from); rv = serv->AsyncConvertData(from.get(), "uncompressed", - mListener, - mListenerContext, + nextListener, + aCtxt, getter_AddRefs(converter)); if (NS_FAILED(rv)) { LOG(("Unexpected failure of AsyncConvertData %s\n", val)); @@ -668,14 +672,15 @@ HttpBaseChannel::ApplyContentConversions() } LOG(("converter removed '%s' content-encoding\n", val)); - mListener = converter; + nextListener = converter; } else { if (val) LOG(("Unknown content encoding '%s', ignoring\n", val)); } } - + *aNewNextListener = nextListener; + NS_ADDREF(*aNewNextListener); return NS_OK; } diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index e2da7b14ce7f..9e4b3f89233f 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -240,7 +240,9 @@ protected: // drop reference to listener, its callbacks, and the progress sink void ReleaseListeners(); - nsresult ApplyContentConversions(); + NS_IMETHOD DoApplyContentConversions(nsIStreamListener *aNextListener, + nsIStreamListener **aNewNextListener, + nsISupports *aCtxt); void AddCookiesToRequest(); virtual nsresult SetupReplacementChannel(nsIURI *, diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index f3efdbaddf82..72607dbf8b5e 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -336,9 +336,14 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus, if (mResponseHead) SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie)); - rv = ApplyContentConversions(); - if (NS_FAILED(rv)) + nsCOMPtr listener; + rv = DoApplyContentConversions(mListener, getter_AddRefs(listener), + mListenerContext); + if (NS_FAILED(rv)) { Cancel(rv); + } else if (listener) { + mListener = listener; + } mSelfAddr = selfAddr; mPeerAddr = peerAddr; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index d2475a01c9e7..026f7f9325e5 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -868,6 +868,7 @@ nsHttpChannel::CallOnStartRequest() ((mResponseHead->ContentType().EqualsLiteral(APPLICATION_OCTET_STREAM) && (mLoadFlags & LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN)))); + bool unknownDecoderStarted = false; if (shouldSniff) { MOZ_ASSERT(mConnectionInfo, "Should have connection info here"); if (!mContentTypeHint.IsEmpty()) @@ -877,10 +878,6 @@ nsHttpChannel::CallOnStartRequest() mResponseHead->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN)); else { // Uh-oh. We had better find out what type we are! - - // XXX This does not work with content-encodings... but - // neither does applying the conversion from the URILoader - nsCOMPtr serv; rv = gHttpHandler-> GetStreamConverterService(getter_AddRefs(serv)); @@ -894,6 +891,7 @@ nsHttpChannel::CallOnStartRequest() getter_AddRefs(converter)); if (NS_SUCCEEDED(rv)) { mListener = converter; + unknownDecoderStarted = true; } } } @@ -924,9 +922,20 @@ nsHttpChannel::CallOnStartRequest() NS_WARNING("OnStartRequest skipped because of null listener"); } - // install stream converter if required - rv = ApplyContentConversions(); - if (NS_FAILED(rv)) return rv; + // Install stream converter if required. + // If we use unknownDecoder, stream converters will be installed later (in + // nsUnknownDecoder) after OnStartRequest is called for the real listener. + if (!unknownDecoderStarted) { + nsCOMPtr listener; + nsISupports *ctxt = mListenerContext; + rv = DoApplyContentConversions(mListener, getter_AddRefs(listener), ctxt); + if (NS_FAILED(rv)) { + return rv; + } + if (listener) { + mListener = listener; + } + } rv = EnsureAssocReq(); if (NS_FAILED(rv)) diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.cpp b/netwerk/streamconv/converters/nsUnknownDecoder.cpp index e2bb90401b6b..c424ac79f2de 100644 --- a/netwerk/streamconv/converters/nsUnknownDecoder.cpp +++ b/netwerk/streamconv/converters/nsUnknownDecoder.cpp @@ -18,16 +18,76 @@ #include "nsIViewSourceChannel.h" #include "nsIHttpChannel.h" #include "nsIForcePendingChannel.h" +#include "nsIEncodedChannel.h" #include "nsNetCID.h" #include "nsNetUtil.h" +#include -#define MAX_BUFFER_SIZE 512 +#define MAX_BUFFER_SIZE 512u + +NS_IMPL_ISUPPORTS(nsUnknownDecoder::ConvertedStreamListener, + nsIStreamListener, + nsIRequestObserver) + +nsUnknownDecoder::ConvertedStreamListener:: + ConvertedStreamListener(nsUnknownDecoder *aDecoder) +{ + mDecoder = aDecoder; +} + +nsUnknownDecoder::ConvertedStreamListener::~ConvertedStreamListener() +{ +} + +NS_IMETHODIMP +nsUnknownDecoder::ConvertedStreamListener:: + AppendDataToString(nsIInputStream* inputStream, + void* closure, + const char* rawSegment, + uint32_t toOffset, + uint32_t count, + uint32_t* writeCount) +{ + nsCString* decodedData = static_cast(closure); + decodedData->Append(rawSegment, count); + *writeCount = count; + return NS_OK; +} + +NS_IMETHODIMP +nsUnknownDecoder::ConvertedStreamListener::OnStartRequest(nsIRequest* request, + nsISupports* context) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsUnknownDecoder::ConvertedStreamListener:: + OnDataAvailable(nsIRequest* request, + nsISupports* context, + nsIInputStream* stream, + uint64_t offset, + uint32_t count) +{ + uint32_t read; + return stream->ReadSegments(AppendDataToString, &mDecoder->mDecodedData, count, + &read); +} + +NS_IMETHODIMP +nsUnknownDecoder::ConvertedStreamListener::OnStopRequest(nsIRequest* request, + nsISupports* context, + nsresult status) +{ + return NS_OK; +} nsUnknownDecoder::nsUnknownDecoder() : mBuffer(nullptr) , mBufferLen(0) , mRequireHTMLsuffix(false) + , mDecodedData("") { nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefs) { @@ -314,12 +374,26 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) NS_ASSERTION(mContentType.IsEmpty(), "Content type is already known."); if (!mContentType.IsEmpty()) return; + const char* testData = mBuffer; + uint32_t testDataLen = mBufferLen; + // Check if data are compressed. + nsCOMPtr channel(do_QueryInterface(aRequest)); + if (channel) { + nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen); + if (NS_SUCCEEDED(rv)) { + if (!mDecodedData.IsEmpty()) { + testData = mDecodedData.get(); + testDataLen = std::min(mDecodedData.Length(), MAX_BUFFER_SIZE); + } + } + } + // First, run through all the types we can detect reliably based on // magic numbers uint32_t i; for (i = 0; i < sSnifferEntryNum; ++i) { - if (mBufferLen >= sSnifferEntries[i].mByteLen && // enough data - memcmp(mBuffer, sSnifferEntries[i].mBytes, sSnifferEntries[i].mByteLen) == 0) { // and type matches + if (testDataLen >= sSnifferEntries[i].mByteLen && // enough data + memcmp(testData, sSnifferEntries[i].mBytes, sSnifferEntries[i].mByteLen) == 0) { // and type matches NS_ASSERTION(sSnifferEntries[i].mMimeType || sSnifferEntries[i].mContentTypeSniffer, "Must have either a type string or a function to set the type"); @@ -342,7 +416,7 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) } NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest, - (const uint8_t*)mBuffer, mBufferLen, mContentType); + (const uint8_t*)testData, testDataLen, mContentType); if (!mContentType.IsEmpty()) { return; } @@ -376,10 +450,18 @@ bool nsUnknownDecoder::SniffForHTML(nsIRequest* aRequest) if (!AllowSniffing(aRequest)) { return false; } - + // Now look for HTML. - const char* str = mBuffer; - const char* end = mBuffer + mBufferLen; + const char* str; + const char* end; + if (mDecodedData.IsEmpty()) { + str = mBuffer; + end = mBuffer + mBufferLen; + } else { + str = mDecodedData.get(); + end = mDecodedData.get() + std::min(mDecodedData.Length(), + MAX_BUFFER_SIZE); + } // skip leading whitespace while (str != end && nsCRT::IsAsciiSpace(*str)) { @@ -493,38 +575,48 @@ bool nsUnknownDecoder::LastDitchSniff(nsIRequest* aRequest) // All we can do now is try to guess whether this is text/plain or // application/octet-stream + const char* testData; + uint32_t testDataLen; + if (mDecodedData.IsEmpty()) { + testData = mBuffer; + testDataLen = mBufferLen; + } else { + testData = mDecodedData.get(); + testDataLen = std::min(mDecodedData.Length(), MAX_BUFFER_SIZE); + } + // First, check for a BOM. If we see one, assume this is text/plain // in whatever encoding. If there is a BOM _and_ text we will // always have at least 4 bytes in the buffer (since the 2-byte BOMs // are for 2-byte encodings and the UTF-8 BOM is 3 bytes). - if (mBufferLen >= 4) { - const unsigned char* buf = (const unsigned char*)mBuffer; + if (testDataLen >= 4) { + const unsigned char* buf = (const unsigned char*)testData; if ((buf[0] == 0xFE && buf[1] == 0xFF) || // UTF-16, Big Endian (buf[0] == 0xFF && buf[1] == 0xFE) || // UTF-16 or UCS-4, Little Endian (buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) || // UTF-8 (buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)) { // UCS-4, Big Endian - + mContentType = TEXT_PLAIN; return true; } } - + // Now see whether the buffer has any non-text chars. If not, then let's // just call it text/plain... // uint32_t i; - for (i = 0; i < mBufferLen && IS_TEXT_CHAR(mBuffer[i]); i++) { + for (i = 0; i < testDataLen && IS_TEXT_CHAR(testData[i]); i++) { continue; } - if (i == mBufferLen) { + if (i == testDataLen) { mContentType = TEXT_PLAIN; } else { mContentType = APPLICATION_OCTET_STREAM; } - return true; + return true; } @@ -562,6 +654,18 @@ nsresult nsUnknownDecoder::FireListenerNotifications(nsIRequest* request, // Fire the OnStartRequest(...) rv = mNextListener->OnStartRequest(request, aCtxt); + if (NS_SUCCEEDED(rv)) { + // install stream converter if required + nsCOMPtr encodedChannel = do_QueryInterface(request); + if (encodedChannel) { + nsCOMPtr listener; + rv = encodedChannel->DoApplyContentConversions(mNextListener, getter_AddRefs(listener), aCtxt); + if (NS_SUCCEEDED(rv) && listener) { + mNextListener = listener; + } + } + } + if (!mBuffer) return NS_ERROR_OUT_OF_MEMORY; // If the request was canceled, then we need to treat that equivalently @@ -600,6 +704,51 @@ nsresult nsUnknownDecoder::FireListenerNotifications(nsIRequest* request, return rv; } + +nsresult +nsUnknownDecoder::ConvertEncodedData(nsIRequest* request, + const char* data, + uint32_t length) +{ + nsresult rv = NS_OK; + + mDecodedData = ""; + nsCOMPtr encodedChannel(do_QueryInterface(request)); + if (encodedChannel) { + + nsRefPtr strListener = + new ConvertedStreamListener(this); + + nsCOMPtr listener; + rv = encodedChannel->DoApplyContentConversions(strListener, + getter_AddRefs(listener), + nullptr); + + if (NS_FAILED(rv)) { + return rv; + } + + if (listener) { + listener->OnStartRequest(request, nullptr); + + nsCOMPtr rawStream = + do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID); + if (!rawStream) + return NS_ERROR_FAILURE; + + rv = rawStream->SetData((const char*)data, length); + NS_ENSURE_SUCCESS(rv, rv); + + rv = listener->OnDataAvailable(request, nullptr, rawStream, 0, + length); + NS_ENSURE_SUCCESS(rv, rv); + + listener->OnStopRequest(request, nullptr, NS_OK); + } + } + return rv; +} + void nsBinaryDetector::DetermineContentType(nsIRequest* aRequest) { diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.h b/netwerk/streamconv/converters/nsUnknownDecoder.h index f785a8cb7d7e..ed2f40bddf80 100644 --- a/netwerk/streamconv/converters/nsUnknownDecoder.h +++ b/netwerk/streamconv/converters/nsUnknownDecoder.h @@ -47,6 +47,26 @@ protected: virtual void DetermineContentType(nsIRequest* aRequest); nsresult FireListenerNotifications(nsIRequest* request, nsISupports *aCtxt); + class ConvertedStreamListener: public nsIStreamListener + { + public: + ConvertedStreamListener(nsUnknownDecoder *aDecoder); + + NS_DECL_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + + private: + virtual ~ConvertedStreamListener(); + static NS_METHOD AppendDataToString(nsIInputStream* inputStream, + void* closure, + const char* rawSegment, + uint32_t toOffset, + uint32_t count, + uint32_t* writeCount); + nsUnknownDecoder *mDecoder; + }; + protected: nsCOMPtr mNextListener; @@ -106,6 +126,10 @@ protected: nsCString mContentType; +protected: + nsresult ConvertEncodedData(nsIRequest* request, const char* data, + uint32_t length); + nsCString mDecodedData; // If data are encoded this will be uncompress data. }; #define NS_BINARYDETECTOR_CID \ diff --git a/netwerk/test/unit/test_reply_without_content_type.js b/netwerk/test/unit/test_reply_without_content_type.js index 2cbda6dafb5f..33501de34918 100644 --- a/netwerk/test/unit/test_reply_without_content_type.js +++ b/netwerk/test/unit/test_reply_without_content_type.js @@ -7,27 +7,44 @@ Cu.import("resource://testing-common/httpd.js"); var httpserver = new HttpServer(); -var testpath = "/simple"; +var testpath = "/simple_plainText"; var httpbody = "omg hai"; +var testpathGZip = "/simple_gzip"; +//this is compressed httpbody; +var httpbodyGZip = ["0x1f", "0x8b", "0x8", "0x0", "0x0", "0x0", "0x0", "0x0", + "0x0", "0x3", "0xb3", "0xc9", "0x28", "0xc9", "0xcd", "0xb1", + "0xb3", "0x49", "0xca", "0x4f", "0xa9", "0xb4", "0xcb", + "0xcf", "0x4d", "0x57", "0xc8", "0x48", "0xcc", "0xb4", + "0xd1", "0x7", "0xf3", "0x6c", "0xf4", "0xc1", "0x52", "0x0", + "0x4", "0x99", "0x79", "0x2b", "0x21", "0x0", "0x0", "0x0"]; var buffer = ""; var dbg=0 if (dbg) { print("============== START =========="); } -function run_test() { - setup_test(); - do_test_pending(); -} - -function setup_test() { - if (dbg) { print("============== setup_test: in"); } - httpserver.registerPathHandler(testpath, serverHandler); +add_test(function test_plainText() { + if (dbg) { print("============== test_plainText: in"); } + httpserver.registerPathHandler(testpath, serverHandler_plainText); httpserver.start(-1); var channel = setupChannel(testpath); // ChannelListener defined in head_channels.js channel.asyncOpen(new ChannelListener(checkRequest, channel), null); - if (dbg) { print("============== setup_test: out"); } -} + do_test_pending(); + if (dbg) { print("============== test_plainText: out"); } +}); + +add_test(function test_GZip() { + if (dbg) { print("============== test_GZip: in"); } + httpserver.registerPathHandler(testpathGZip, serverHandler_GZip); + httpserver.start(-1); + var channel = setupChannel(testpathGZip); + // ChannelListener defined in head_channels.js + channel.asyncOpen(new ChannelListener(checkRequest, channel, + CL_EXPECT_GZIP), null); + do_test_pending(); + if (dbg) { print("============== test_GZip: out"); } +}); + function setupChannel(path) { var ios = Cc["@mozilla.org/network/io-service;1"]. @@ -39,12 +56,24 @@ function setupChannel(path) { return chan; } -function serverHandler(metadata, response) { - if (dbg) { print("============== serverHandler: in"); } +function serverHandler_plainText(metadata, response) { + if (dbg) { print("============== serverHandler plainText: in"); } // no content type set // response.setHeader("Content-Type", "text/plain", false); response.bodyOutputStream.write(httpbody, httpbody.length); - if (dbg) { print("============== serverHandler: out"); } + if (dbg) { print("============== serverHandler plainText: out"); } +} + +function serverHandler_GZip(metadata, response) { + if (dbg) { print("============== serverHandler GZip: in"); } + // no content type set + // response.setHeader("Content-Type", "text/plain", false); + response.setHeader("Content-Encoding", "gzip", false); + var bos = Cc["@mozilla.org/binaryoutputstream;1"] + .createInstance(Ci.nsIBinaryOutputStream); + bos.setOutputStream(response.bodyOutputStream); + bos.writeByteArray(httpbodyGZip, httpbodyGZip.length); + if (dbg) { print("============== serverHandler GZip: out"); } } function checkRequest(request, data, context) { @@ -52,6 +81,10 @@ function checkRequest(request, data, context) { do_check_eq(data, httpbody); do_check_eq(request.QueryInterface(Ci.nsIChannel).contentType,"text/html"); httpserver.stop(do_test_finished); + run_next_test(); if (dbg) { print("============== checkRequest: out"); } } +function run_test() { + run_next_test(); +} From f4a67332e81d014b93f5bd93b3350605d76f23aa Mon Sep 17 00:00:00 2001 From: Cykesiopka Date: Tue, 12 Aug 2014 22:24:00 -0400 Subject: [PATCH 26/86] Bug 1052257 - Add and use error code specific to inadequate key sizes. r=keeler --- .../locales/en-US/chrome/pipnss/nsserrors.properties | 1 + security/manager/ssl/src/nsUsageArrayHelper.cpp | 1 + security/manager/ssl/tests/unit/head_psm.js | 1 + security/manager/ssl/tests/unit/test_keysize.js | 4 ++-- security/manager/ssl/tests/unit/test_ocsp_stapling.js | 3 ++- security/pkix/include/pkix/Result.h | 1 + security/pkix/include/pkix/pkixnss.h | 3 ++- security/pkix/lib/pkixnss.cpp | 9 ++++++--- 8 files changed, 16 insertions(+), 7 deletions(-) diff --git a/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties b/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties index 188222a2c63e..4567761d82f8 100644 --- a/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties +++ b/security/manager/locales/en-US/chrome/pipnss/nsserrors.properties @@ -299,3 +299,4 @@ SEC_ERROR_LOCKED_PASSWORD=The password is locked. SEC_ERROR_UNKNOWN_PKCS11_ERROR=Unknown PKCS #11 error. SEC_ERROR_BAD_CRL_DP_URL=Invalid or unsupported URL in CRL distribution point name. SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED=The certificate was signed using a signature algorithm that is disabled because it is not secure. +MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE=The server presented a certificate with a key size that is too small to establish a secure connection. diff --git a/security/manager/ssl/src/nsUsageArrayHelper.cpp b/security/manager/ssl/src/nsUsageArrayHelper.cpp index e5a895377199..5777a4e6d68a 100644 --- a/security/manager/ssl/src/nsUsageArrayHelper.cpp +++ b/security/manager/ssl/src/nsUsageArrayHelper.cpp @@ -150,6 +150,7 @@ nsUsageArrayHelper::verifyFailed(uint32_t *_verified, int err) case SEC_ERROR_INADEQUATE_CERT_TYPE: case SEC_ERROR_CA_CERT_INVALID: case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: + case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: *_verified = nsNSSCertificate::USAGE_NOT_ALLOWED; break; /* These are the cases that have individual error messages */ case SEC_ERROR_REVOKED_CERTIFICATE: diff --git a/security/manager/ssl/tests/unit/head_psm.js b/security/manager/ssl/tests/unit/head_psm.js index c62073572a4f..9741ea820901 100644 --- a/security/manager/ssl/tests/unit/head_psm.js +++ b/security/manager/ssl/tests/unit/head_psm.js @@ -60,6 +60,7 @@ const SSL_ERROR_BAD_CERT_DOMAIN = SSL_ERROR_BASE + 12; const SSL_ERROR_BAD_CERT_ALERT = SSL_ERROR_BASE + 17; const MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = MOZILLA_PKIX_ERROR_BASE + 0; +const MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = MOZILLA_PKIX_ERROR_BASE + 2; // -16382 // Supported Certificate Usages const certificateUsageSSLClient = 0x0001; diff --git a/security/manager/ssl/tests/unit/test_keysize.js b/security/manager/ssl/tests/unit/test_keysize.js index 4333194dbe9c..0006d9fcf3f4 100644 --- a/security/manager/ssl/tests/unit/test_keysize.js +++ b/security/manager/ssl/tests/unit/test_keysize.js @@ -44,12 +44,12 @@ function check_ok_ca(cert) { } function check_fail(cert) { - return check_cert_err(cert, SEC_ERROR_INVALID_KEY); + return check_cert_err(cert, MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE); } function check_fail_ca(cert) { return check_cert_err_generic(cert, - SEC_ERROR_INVALID_KEY, + MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE, certificateUsageSSLCA); } diff --git a/security/manager/ssl/tests/unit/test_ocsp_stapling.js b/security/manager/ssl/tests/unit/test_ocsp_stapling.js index 5591560602ca..0f843b730dfa 100644 --- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js +++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js @@ -141,7 +141,8 @@ function add_tests(certDB, otherTestCA) { // Check that OCSP responder certificates with key sizes below 1024 bits are // rejected, even when the main certificate chain keys are at least 1024 bits. add_ocsp_test("keysize-ocsp-delegated.example.com", - getXPCOMStatusFromNSS(SEC_ERROR_INVALID_KEY), true); + getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE), + true); } function check_ocsp_stapling_telemetry() { diff --git a/security/pkix/include/pkix/Result.h b/security/pkix/include/pkix/Result.h index 1fff4c64569d..19dca5cfc15a 100644 --- a/security/pkix/include/pkix/Result.h +++ b/security/pkix/include/pkix/Result.h @@ -78,6 +78,7 @@ MOZILLA_PKIX_ENUM_CLASS Result ERROR_UNSUPPORTED_KEYALG = 37, ERROR_EXPIRED_ISSUER_CERTIFICATE = 38, ERROR_CA_CERT_USED_AS_END_ENTITY = 39, + ERROR_INADEQUATE_KEY_SIZE = 40, // Keep this in sync with MAP_LIST in pkixnss.cpp diff --git a/security/pkix/include/pkix/pkixnss.h b/security/pkix/include/pkix/pkixnss.h index 721e7f048344..7dfef1175fa8 100644 --- a/security/pkix/include/pkix/pkixnss.h +++ b/security/pkix/include/pkix/pkixnss.h @@ -72,7 +72,8 @@ static const PRErrorCode ERROR_LIMIT = ERROR_BASE + 1000; enum ErrorCode { MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = ERROR_BASE + 0, - MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1 + MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = ERROR_BASE + 1, + MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE = ERROR_BASE + 2 }; void RegisterErrorTable(); diff --git a/security/pkix/lib/pkixnss.cpp b/security/pkix/lib/pkixnss.cpp index 8b66902f7345..477c75f91eee 100644 --- a/security/pkix/lib/pkixnss.cpp +++ b/security/pkix/lib/pkixnss.cpp @@ -64,8 +64,7 @@ CheckPublicKeySize(Input subjectPublicKeyInfo, case rsaKey: // TODO(bug 622859): Enforce a minimum of 2048 bits for EV certs. if (SECKEY_PublicKeyStrengthInBits(publicKey.get()) < MINIMUM_NON_ECC_BITS) { - // TODO(bug 1031946): Create a new error code. - return Result::ERROR_INVALID_KEY; + return Result::ERROR_INADEQUATE_KEY_SIZE; } break; case nullKey: @@ -232,6 +231,7 @@ DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen) MAP(Result::ERROR_UNSUPPORTED_KEYALG, SEC_ERROR_UNSUPPORTED_KEYALG) \ MAP(Result::ERROR_EXPIRED_ISSUER_CERTIFICATE, SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \ MAP(Result::ERROR_CA_CERT_USED_AS_END_ENTITY, MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \ + MAP(Result::ERROR_INADEQUATE_KEY_SIZE, MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \ MAP(Result::FATAL_ERROR_INVALID_ARGS, SEC_ERROR_INVALID_ARGS) \ MAP(Result::FATAL_ERROR_INVALID_STATE, PR_INVALID_STATE_ERROR) \ MAP(Result::FATAL_ERROR_LIBRARY_FAILURE, SEC_ERROR_LIBRARY_FAILURE) \ @@ -302,7 +302,10 @@ RegisterErrorTable() { "MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY", "The server uses a certificate with a basic constraints extension " "identifying it as a certificate authority. For a properly-issued " - "certificate, this should not be the case." } + "certificate, this should not be the case." }, + { "MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE", + "The server presented a certificate with a key size that is too small " + "to establish a secure connection." } }; static const struct PRErrorTable ErrorTable = { From 8614e809aad1096309d7c7dec3ba662f5e2b76dd Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Thu, 14 Aug 2014 14:32:59 +1000 Subject: [PATCH 27/86] Bug 1052383 - Minor style fixes. r=rillian --- content/media/fmp4/apple/AppleATDecoder.cpp | 33 +++++++++++---------- content/media/fmp4/apple/AppleUtils.cpp | 4 +-- content/media/fmp4/apple/AppleUtils.h | 2 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/content/media/fmp4/apple/AppleATDecoder.cpp b/content/media/fmp4/apple/AppleATDecoder.cpp index a0916aaf6bd0..cedde89d3bfb 100644 --- a/content/media/fmp4/apple/AppleATDecoder.cpp +++ b/content/media/fmp4/apple/AppleATDecoder.cpp @@ -61,10 +61,10 @@ AppleATDecoder::~AppleATDecoder() } static void -_MetadataCallback(void *aDecoder, +_MetadataCallback(void* aDecoder, AudioFileStreamID aStream, AudioFileStreamPropertyID aProperty, - UInt32 *aFlags) + UInt32* aFlags) { LOG("AppleATDecoder metadata callback"); AppleATDecoder* decoder = static_cast(aDecoder); @@ -72,10 +72,11 @@ _MetadataCallback(void *aDecoder, } static void -_SampleCallback(void *aDecoder, - UInt32 aNumBytes, UInt32 aNumPackets, - const void *aData, - AudioStreamPacketDescription *aPackets) +_SampleCallback(void* aDecoder, + UInt32 aNumBytes, + UInt32 aNumPackets, + const void* aData, + AudioStreamPacketDescription* aPackets) { LOG("AppleATDecoder sample callback %u bytes %u packets", aNumBytes, aNumPackets); @@ -180,8 +181,8 @@ struct PassthroughUserData { AppleATDecoder* mDecoder; UInt32 mNumPackets; UInt32 mDataSize; - const void *mData; - AudioStreamPacketDescription *mPacketDesc; + const void* mData; + AudioStreamPacketDescription* mPacketDesc; bool mDone; }; @@ -191,12 +192,12 @@ const uint32_t kNeedMoreData = 'MOAR'; static OSStatus _PassthroughInputDataCallback(AudioConverterRef aAudioConverter, - UInt32 *aNumDataPackets /* in/out */, - AudioBufferList *aData /* in/out */, - AudioStreamPacketDescription **aPacketDesc, - void *aUserData) + UInt32* aNumDataPackets /* in/out */, + AudioBufferList* aData /* in/out */, + AudioStreamPacketDescription** aPacketDesc, + void* aUserData) { - PassthroughUserData *userData = (PassthroughUserData *)aUserData; + PassthroughUserData* userData = (PassthroughUserData*)aUserData; if (userData->mDone) { // We make sure this callback is run _once_, with all the data we received // from |AudioFileStreamParseBytes|. When we return an error, the decoder @@ -217,7 +218,7 @@ _PassthroughInputDataCallback(AudioConverterRef aAudioConverter, aData->mBuffers[0].mNumberChannels = userData->mDecoder->mConfig.channel_count; aData->mBuffers[0].mDataByteSize = userData->mDataSize; - aData->mBuffers[0].mData = const_cast(userData->mData); + aData->mBuffers[0].mData = const_cast(userData->mData); return noErr; } @@ -290,9 +291,9 @@ AppleATDecoder::SampleCallback(uint32_t aNumBytes, LOG("pushed audio at time %lfs; duration %lfs\n", (double)time / USECS_PER_S, (double)duration / USECS_PER_S); - AudioData *audio = new AudioData(mSamplePosition, + AudioData* audio = new AudioData(mSamplePosition, time, duration, numFrames, - reinterpret_cast(decoded.forget()), + reinterpret_cast(decoded.forget()), channels, rate); mCallback->Output(audio); mHaveOutput = true; diff --git a/content/media/fmp4/apple/AppleUtils.cpp b/content/media/fmp4/apple/AppleUtils.cpp index f0a0fe517171..5fb362a31de5 100644 --- a/content/media/fmp4/apple/AppleUtils.cpp +++ b/content/media/fmp4/apple/AppleUtils.cpp @@ -26,12 +26,12 @@ namespace mozilla { nsresult AppleUtils::GetProperty(AudioFileStreamID aAudioFileStream, AudioFileStreamPropertyID aPropertyID, - void *aData) + void* aData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aAudioFileStream, aPropertyID, - &size, &writeable); + &size, &writeable); if (rv) { WARN("Couldn't get property " PROPERTY_ID_FORMAT "\n", diff --git a/content/media/fmp4/apple/AppleUtils.h b/content/media/fmp4/apple/AppleUtils.h index 9a0a8b93e212..22573a2a445c 100644 --- a/content/media/fmp4/apple/AppleUtils.h +++ b/content/media/fmp4/apple/AppleUtils.h @@ -16,7 +16,7 @@ struct AppleUtils { // Helper to retrieve properties from AudioFileStream objects. static nsresult GetProperty(AudioFileStreamID aAudioFileStream, AudioFileStreamPropertyID aPropertyID, - void *aData); + void* aData); // Helper to set a string, string pair on a CFMutableDictionaryRef. static void SetCFDict(CFMutableDictionaryRef dict, From d9fdbee68bcc6150b5679fcc2cb17d2e3fb963ba Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Fri, 15 Aug 2014 15:52:18 +1000 Subject: [PATCH 28/86] Bug 1052383 - Properly detect HE-AAC stream. r=rillian --- content/media/fmp4/apple/AppleATDecoder.cpp | 17 ++++--- content/media/fmp4/apple/AppleUtils.cpp | 49 ++++++++++++++++++++- content/media/fmp4/apple/AppleUtils.h | 6 +++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/content/media/fmp4/apple/AppleATDecoder.cpp b/content/media/fmp4/apple/AppleATDecoder.cpp index cedde89d3bfb..666261505cf7 100644 --- a/content/media/fmp4/apple/AppleATDecoder.cpp +++ b/content/media/fmp4/apple/AppleATDecoder.cpp @@ -313,9 +313,14 @@ void AppleATDecoder::SetupDecoder() { AudioStreamBasicDescription inputFormat; - // Fill in the input format description from the stream. - AppleUtils::GetProperty(mStream, - kAudioFileStreamProperty_DataFormat, &inputFormat); + + mHaveOutput = false; + + nsresult rv = AppleUtils::GetRichestDecodableFormat(mStream, inputFormat); + if (NS_FAILED(rv)) { + mCallback->Error(); + return; + } // Fill in the output format manually. PodZero(&mOutputFormat); @@ -335,13 +340,13 @@ AppleATDecoder::SetupDecoder() mOutputFormat.mBytesPerPacket = mOutputFormat.mBytesPerFrame = mOutputFormat.mChannelsPerFrame * mOutputFormat.mBitsPerChannel / 8; - OSStatus rv = AudioConverterNew(&inputFormat, &mOutputFormat, &mConverter); - if (rv) { + OSStatus status = + AudioConverterNew(&inputFormat, &mOutputFormat, &mConverter); + if (status) { LOG("Error %d constructing AudioConverter", rv); mConverter = nullptr; mCallback->Error(); } - mHaveOutput = false; } void diff --git a/content/media/fmp4/apple/AppleUtils.cpp b/content/media/fmp4/apple/AppleUtils.cpp index 5fb362a31de5..2894248bc128 100644 --- a/content/media/fmp4/apple/AppleUtils.cpp +++ b/content/media/fmp4/apple/AppleUtils.cpp @@ -4,9 +4,9 @@ // Utility functions to help with Apple API calls. -#include #include "AppleUtils.h" #include "prlog.h" +#include "nsAutoPtr.h" #ifdef PR_LOGGING PRLogModuleInfo* GetDemuxerLog(); @@ -80,5 +80,52 @@ AppleUtils::SetCFDict(CFMutableDictionaryRef dict, CFDictionarySetValue(dict, keyRef, value ? kCFBooleanTrue : kCFBooleanFalse); } +nsresult +AppleUtils::GetRichestDecodableFormat(AudioFileStreamID aAudioFileStream, + AudioStreamBasicDescription& aFormat) +{ + // Fill in the default format description from the stream. + nsresult rv = GetProperty(aAudioFileStream, + kAudioFileStreamProperty_DataFormat, &aFormat); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + UInt32 propertySize; + OSStatus status = AudioFileStreamGetPropertyInfo( + aAudioFileStream, kAudioFileStreamProperty_FormatList, &propertySize, NULL); + if (NS_WARN_IF(status)) { + // Return the default format description. + return NS_OK; + } + + MOZ_ASSERT(propertySize % sizeof(AudioFormatListItem) == 0); + uint32_t sizeList = propertySize / sizeof(AudioFormatListItem); + nsAutoArrayPtr formatListPtr( + new AudioFormatListItem[sizeList]); + + rv = GetProperty(aAudioFileStream, kAudioFileStreamProperty_FormatList, + formatListPtr); + if (NS_WARN_IF(NS_FAILED(rv))) { + // Return the default format description. + return NS_OK; + } + + // Get the index number of the first playable format. + // This index number will be for the highest quality layer the platform + // is capable of playing. + UInt32 itemIndex; + UInt32 indexSize = sizeof(itemIndex); + status = + AudioFormatGetProperty(kAudioFormatProperty_FirstPlayableFormatFromList, + propertySize, formatListPtr, &indexSize, &itemIndex); + if (NS_WARN_IF(status)) { + // Return the default format description. + return NS_OK; + } + aFormat = formatListPtr[itemIndex].mASBD; + + return NS_OK; +} } // namespace mozilla diff --git a/content/media/fmp4/apple/AppleUtils.h b/content/media/fmp4/apple/AppleUtils.h index 22573a2a445c..d15f4881af84 100644 --- a/content/media/fmp4/apple/AppleUtils.h +++ b/content/media/fmp4/apple/AppleUtils.h @@ -30,6 +30,12 @@ struct AppleUtils { static void SetCFDict(CFMutableDictionaryRef dict, const char* key, bool value); + + // Helper to retrieve the best audio format available in the given + // audio stream. + // The basic format will be returned by default should an error occur. + static nsresult GetRichestDecodableFormat( + AudioFileStreamID aAudioFileStream, AudioStreamBasicDescription& aFormat); }; // Wrapper class to call CFRelease on reference types From 43aad61439f16b22d26198d05b8a74a8e7aaca7a Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Thu, 14 Aug 2014 20:05:00 -0400 Subject: [PATCH 29/86] Bug 1053008 - FlushAndDispatch the ResetDecode call in MDSM::FlushDecoding(). r=kinetik --- content/media/MediaDecoderStateMachine.cpp | 30 +++++++++++----------- content/media/MediaTaskQueue.cpp | 27 +++++++++++++++++++ content/media/MediaTaskQueue.h | 28 ++++++++++++++++++++ 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index f40cd88b3c47..f69cf4ae32f0 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -2443,23 +2443,23 @@ MediaDecoderStateMachine::FlushDecoding() "Should be on state machine or decode thread."); mDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn(); - // Put a task in the decode queue to abort any decoding operations. - // The reader is not supposed to put any tasks to deliver samples into - // the queue after we call this (unless we request another sample from it). - RefPtr task; - task = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode); - mDecodeTaskQueue->Dispatch(task); - { - // Wait for the thread decoding to abort decoding operations and run - // any pending callbacks. This is important, as we don't want any - // pending tasks posted to the task queue by the reader to deliver - // any samples after we've posted the reader Shutdown() task below, - // as the sample-delivery tasks will keep video frames alive until - // after we've called Reader::Shutdown(), and shutdown on B2G will - // fail as there are outstanding video frames alive. + // Put a task in the decode queue to abort any decoding operations. + // The reader is not supposed to put any tasks to deliver samples into + // the queue after this runs (unless we request another sample from it). + RefPtr task; + task = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode); + + // Wait for the ResetDecode to run and for the decoder to abort + // decoding operations and run any pending callbacks. This is + // important, as we don't want any pending tasks posted to the task + // queue by the reader to deliver any samples after we've posted the + // reader Shutdown() task below, as the sample-delivery tasks will + // keep video frames alive until after we've called Reader::Shutdown(), + // and shutdown on B2G will fail as there are outstanding video frames + // alive. ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor()); - mDecodeTaskQueue->Flush(); + mDecodeTaskQueue->FlushAndDispatch(task); } // We must reset playback so that all references to frames queued diff --git a/content/media/MediaTaskQueue.cpp b/content/media/MediaTaskQueue.cpp index c301f2004a99..78df6fef24ab 100644 --- a/content/media/MediaTaskQueue.cpp +++ b/content/media/MediaTaskQueue.cpp @@ -15,6 +15,7 @@ MediaTaskQueue::MediaTaskQueue(TemporaryRef aPool) , mQueueMonitor("MediaTaskQueue::Queue") , mIsRunning(false) , mIsShutdown(false) + , mIsFlushing(false) { MOZ_COUNT_CTOR(MediaTaskQueue); } @@ -30,6 +31,17 @@ nsresult MediaTaskQueue::Dispatch(TemporaryRef aRunnable) { MonitorAutoLock mon(mQueueMonitor); + return DispatchLocked(aRunnable, AbortIfFlushing); +} + +nsresult +MediaTaskQueue::DispatchLocked(TemporaryRef aRunnable, + DispatchMode aMode) +{ + mQueueMonitor.AssertCurrentThreadOwns(); + if (mIsFlushing && aMode == AbortIfFlushing) { + return NS_ERROR_ABORT; + } if (mIsShutdown) { return NS_ERROR_FAILURE; } @@ -113,10 +125,25 @@ MediaTaskQueue::Shutdown() AwaitIdleLocked(); } +nsresult +MediaTaskQueue::FlushAndDispatch(TemporaryRef aRunnable) +{ + MonitorAutoLock mon(mQueueMonitor); + AutoSetFlushing autoFlush(this); + while (!mTasks.empty()) { + mTasks.pop(); + } + nsresult rv = DispatchLocked(aRunnable, IgnoreFlushing); + NS_ENSURE_SUCCESS(rv, rv); + AwaitIdleLocked(); + return NS_OK; +} + void MediaTaskQueue::Flush() { MonitorAutoLock mon(mQueueMonitor); + AutoSetFlushing autoFlush(this); while (!mTasks.empty()) { mTasks.pop(); } diff --git a/content/media/MediaTaskQueue.h b/content/media/MediaTaskQueue.h index 674f775549c8..14c8efa2eb11 100644 --- a/content/media/MediaTaskQueue.h +++ b/content/media/MediaTaskQueue.h @@ -35,6 +35,8 @@ public: nsresult SyncDispatch(TemporaryRef aRunnable); + nsresult FlushAndDispatch(TemporaryRef aRunnable); + // Removes all pending tasks from the task queue, and blocks until // the currently running task (if any) finishes. void Flush(); @@ -59,6 +61,11 @@ private: // mQueueMonitor must be held. void AwaitIdleLocked(); + enum DispatchMode { AbortIfFlushing, IgnoreFlushing }; + + nsresult DispatchLocked(TemporaryRef aRunnable, + DispatchMode aMode); + RefPtr mPool; // Monitor that protects the queue and mIsRunning; @@ -79,6 +86,27 @@ private: // True if we've started our shutdown process. bool mIsShutdown; + class MOZ_STACK_CLASS AutoSetFlushing + { + public: + AutoSetFlushing(MediaTaskQueue* aTaskQueue) : mTaskQueue(aTaskQueue) + { + mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns(); + mTaskQueue->mIsFlushing = true; + } + ~AutoSetFlushing() + { + mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns(); + mTaskQueue->mIsFlushing = false; + } + + private: + MediaTaskQueue* mTaskQueue; + }; + + // True if we're flushing; we reject new tasks if we're flushing. + bool mIsFlushing; + class Runner : public nsRunnable { public: Runner(MediaTaskQueue* aQueue) From bb9e12a5bf56a81de3a3c4af8f31850f01572eb0 Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Thu, 14 Aug 2014 05:45:00 -0400 Subject: [PATCH 30/86] Bug 1026951 - Assertion failure: NS_IsMainThread() (OnStateStop should only be called on the main thread.). r=sworkman --- netwerk/base/src/nsInputStreamPump.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/netwerk/base/src/nsInputStreamPump.cpp b/netwerk/base/src/nsInputStreamPump.cpp index 02bd7e04d035..83e789401e76 100644 --- a/netwerk/base/src/nsInputStreamPump.cpp +++ b/netwerk/base/src/nsInputStreamPump.cpp @@ -469,6 +469,16 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream) // EnsureWaiting isn't blocked by it. mProcessingCallbacks = false; + // We must break the loop when we're switching event delivery to another + // thread and the input stream pump is suspended, otherwise + // OnStateStop() might be called off the main thread. See bug 1026951 + // comment #107 for the exact scenario. + if (mSuspendCount && mRetargeting) { + mState = nextState; + mWaitingForInputStreamReady = false; + break; + } + // Wait asynchronously if there is still data to transfer, or we're // switching event delivery to another thread. if (!mSuspendCount && (stillTransferring || mRetargeting)) { From bafd76a70189b7e802fc010d8436809191b25a4d Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 15 Aug 2014 11:58:53 -0400 Subject: [PATCH 31/86] Bug 1054087 - Disable the test on all Android versions --- editor/libeditor/html/tests/mochitest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/libeditor/html/tests/mochitest.ini b/editor/libeditor/html/tests/mochitest.ini index 558360d498c0..55a44e6db3c3 100644 --- a/editor/libeditor/html/tests/mochitest.ini +++ b/editor/libeditor/html/tests/mochitest.ini @@ -101,7 +101,7 @@ skip-if = os != "win" [test_CF_HTML_clipboard.html] [test_contenteditable_focus.html] [test_dom_input_event_on_htmleditor.html] -skip-if = android_version == "10" # bug 1054087 +skip-if = toolkit == 'android' # bug 1054087 [test_keypress_untrusted_event.html] [test_root_element_replacement.html] [test_select_all_without_body.html] From 9b3d66a3f45eb7c94ac0bd0daf5bf52208757895 Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Thu, 14 Aug 2014 16:21:15 -0400 Subject: [PATCH 32/86] Bug 1052545 - Telemetry experiment branches are not saved correctly: we set the _dirty flag correctly, but then don't write the cache, r=gfritzsche --HG-- extra : rebase_source : 8b531590cb76292b39c83d3928fc0107f1e83424 --- browser/experiments/Experiments.jsm | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/browser/experiments/Experiments.jsm b/browser/experiments/Experiments.jsm index c3bac031eaf6..344fc7de4a1e 100644 --- a/browser/experiments/Experiments.jsm +++ b/browser/experiments/Experiments.jsm @@ -64,6 +64,8 @@ const PREF_TELEMETRY_ENABLED = "enabled"; const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties"; const STRING_TYPE_NAME = "type.%ID%.name"; +const CACHE_WRITE_RETRY_DELAY_SEC = 60 * 3; + const TELEMETRY_LOG = { // log(key, [kind, experimentId, details]) ACTIVATION_KEY: "EXPERIMENT_ACTIVATION", @@ -331,10 +333,19 @@ function AlreadyShutdownError(message="already shut down") { this.message = message; this.stack = error.stack; } - AlreadyShutdownError.prototype = Object.create(Error.prototype); AlreadyShutdownError.prototype.constructor = AlreadyShutdownError; +function CacheWriteError(message="Error writing cache file") { + Error.call(this, message); + let error = new Error(); + this.name = "CacheWriteError"; + this.message = message; + this.stack = error.stack; +} +CacheWriteError.prototype = Object.create(Error.prototype); +CacheWriteError.prototype.constructor = CacheWriteError; + /** * Manages the experiments and provides an interface to control them. */ @@ -690,6 +701,7 @@ Experiments.Experiments.prototype = { throw new Error("Experiment not found"); } e.branch = String(branchstr); + this._log.trace("setExperimentBranch(" + id + ", " + e.branch + ") _dirty=" + this._dirty); this._dirty = true; Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null); yield this._run(); @@ -766,6 +778,8 @@ Experiments.Experiments.prototype = { this._mainTask = Task.spawn(function*() { try { yield this._main(); + } catch (e if e instanceof CacheWriteError) { + // In this case we want to reschedule } catch (e) { this._log.error("_main caught error: " + e); return; @@ -801,7 +815,7 @@ Experiments.Experiments.prototype = { // If somebody called .updateManifest() or disableExperiment() // while we were running, go again right now. } - while (this._refresh || this._terminateReason); + while (this._refresh || this._terminateReason || this._dirty); }, _loadManifest: function*() { @@ -992,7 +1006,7 @@ Experiments.Experiments.prototype = { // We failed to write the cache, it's still dirty. this._dirty = true; this._log.error("_saveToCache failed and caught error: " + e); - return; + throw new CacheWriteError(); } this._log.debug("_saveToCache saved to " + path); @@ -1307,6 +1321,10 @@ Experiments.Experiments.prototype = { let time = null; let now = this._policy.now().getTime(); + if (this._dirty) { + // If we failed to write the cache, we should try again periodically + time = now + 1000 * CACHE_WRITE_RETRY_DELAY_SEC; + } for (let [id, experiment] of this._experiments) { let scheduleTime = experiment.getScheduleTime(); From d2036d7c98677ed730ea3d00d20a2ff19b6597ec Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Thu, 14 Aug 2014 16:21:33 -0400 Subject: [PATCH 33/86] Bug 1054014 - Build bustage in nsTextStore because the end of GetGUIDNameStrWithTable doesn't return a value, r=masayuki --HG-- extra : rebase_source : ef919c1580bd92b74b63bdb39b2926ed199c8563 --- widget/windows/nsTextStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/windows/nsTextStore.cpp b/widget/windows/nsTextStore.cpp index 75886d495a53..6c80cedd5dc4 100644 --- a/widget/windows/nsTextStore.cpp +++ b/widget/windows/nsTextStore.cpp @@ -365,7 +365,7 @@ GetGUIDNameStrWithTable(REFGUID aGUID) #undef RETURN_GUID_NAME - GetGUIDNameStr(aGUID); + return GetGUIDNameStr(aGUID); } static nsCString From aa23f17657ddefe2517aeda7471ef8cff0e4dc9e Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Thu, 14 Aug 2014 16:30:54 -0400 Subject: [PATCH 34/86] Bug 1053836 - Fix subclassing of prefix loggers by only overriding the log() method, not all the other methods. This fixes `this` resolution in the Experiment log override, r=gps --HG-- extra : rebase_source : fd81dc1a5aa15b4b1e57413991a787a463b42945 --- toolkit/modules/Log.jsm | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/toolkit/modules/Log.jsm b/toolkit/modules/Log.jsm index 59b122d768d2..c2c83bc7c6ec 100644 --- a/toolkit/modules/Log.jsm +++ b/toolkit/modules/Log.jsm @@ -497,19 +497,8 @@ LoggerRepository.prototype = { getLoggerWithMessagePrefix: function (name, prefix) { let log = this.getLogger(name); - let proxy = {__proto__: log}; - - for (let level in Log.Level) { - if (level == "Desc") { - continue; - } - - let lc = level.toLowerCase(); - proxy[lc] = function (msg, ...args) { - return log[lc].apply(log, [prefix + msg, ...args]); - }; - } - + let proxy = Object.create(log); + proxy.log = (level, string, params) => log.log(level, prefix + string, params); return proxy; }, }; From f7e2a2780f5a00b54c16bb7eb9a37826b7c51ad9 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Thu, 14 Aug 2014 13:50:25 -0400 Subject: [PATCH 35/86] Bug 1049501: Don't let the GMPThread event loop recurse while handling IPDL shutdowns r=bsmedberg --- content/media/gmp/GMPVideoEncoderParent.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/content/media/gmp/GMPVideoEncoderParent.cpp b/content/media/gmp/GMPVideoEncoderParent.cpp index 816a40cc8b8f..f352945aead5 100644 --- a/content/media/gmp/GMPVideoEncoderParent.cpp +++ b/content/media/gmp/GMPVideoEncoderParent.cpp @@ -12,6 +12,7 @@ #include "nsAutoRef.h" #include "GMPParent.h" #include "mozilla/gmp/GMPTypes.h" +#include "nsThread.h" #include "nsThreadUtils.h" #include "runnable_utils.h" @@ -72,7 +73,9 @@ GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin) GMPVideoEncoderParent::~GMPVideoEncoderParent() { - mEncodedThread->Shutdown(); + if (mEncodedThread) { + mEncodedThread->Shutdown(); + } } GMPVideoHostImpl& @@ -238,6 +241,12 @@ GMPVideoEncoderParent::Shutdown() } } +static void +ShutdownEncodedThread(nsCOMPtr& aThread) +{ + aThread->Shutdown(); +} + // Note: Keep this sync'd up with Shutdown void GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) @@ -249,6 +258,15 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) mCallback->Terminated(); mCallback = nullptr; } + // Must be shut down before VideoEncoderDestroyed(), since this can recurse + // the GMPThread event loop. See bug 1049501 + if (mEncodedThread) { + // Can't get it to allow me to use WrapRunnable with a nsCOMPtr() + NS_DispatchToMainThread( + WrapRunnableNM >(&ShutdownEncodedThread, mEncodedThread)); + mEncodedThread = nullptr; + } if (mPlugin) { // Ignore any return code. It is OK for this to fail without killing the process. mPlugin->VideoEncoderDestroyed(this); From 28be0fa9302ae3d2d67c7a19abe126c94b231c77 Mon Sep 17 00:00:00 2001 From: William Lachance Date: Fri, 15 Aug 2014 12:59:02 -0400 Subject: [PATCH 36/86] Bug 1051895 - Make mozdevice docs a bit easier to navigate;r=bc DONTBUILD NPOTB --- testing/mozbase/docs/devicemanagement.rst | 2 +- testing/mozbase/docs/mozdevice.rst | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/testing/mozbase/docs/devicemanagement.rst b/testing/mozbase/docs/devicemanagement.rst index 6897ca9264e9..80c4af5bdbd8 100644 --- a/testing/mozbase/docs/devicemanagement.rst +++ b/testing/mozbase/docs/devicemanagement.rst @@ -6,6 +6,6 @@ running automated tests or scripts on a device (e.g. an Android- or FirefoxOS-based phone) connected to a workstation. .. toctree:: - :maxdepth: 2 + :maxdepth: 3 mozdevice diff --git a/testing/mozbase/docs/mozdevice.rst b/testing/mozbase/docs/mozdevice.rst index 9ce288b9ba0a..1cbbfd9fdf8a 100644 --- a/testing/mozbase/docs/mozdevice.rst +++ b/testing/mozbase/docs/mozdevice.rst @@ -6,17 +6,17 @@ such as an Android- or FirefoxOS-based phone. It allows you to push files to these types of devices, launch processes, and more. There are currently two available interfaces: -* DeviceManager: an interface to a device that works either via ADB or - a custom TCP protocol (the latter requires an agent application - running on the device). -* ADB: a similar interface that uses Android Debugger Protocol - explicitly +* :ref:`DeviceManager`: Works either via ADB or a custom TCP protocol + (the latter requires an agent application running on the device). +* :ref:`ADB`: Uses the Android Debugger Protocol explicitly In general, new code should use the ADB abstraction where possible as it is simpler and more reliable. .. automodule:: mozdevice +.. _DeviceManager: + DeviceManager interface ----------------------- .. autoclass:: DeviceManager @@ -85,12 +85,10 @@ Application management methods .. automethod:: DeviceManager.updateApp(self, appBundlePath, processName=None, destPath=None, ipAddr=None, port=30000) DeviceManagerADB implementation -------------------------------- +``````````````````````````````` .. autoclass:: mozdevice.DeviceManagerADB -ADB-specific methods -```````````````````` DeviceManagerADB has several methods that are not present in all DeviceManager implementations. Please do not use them in code that is meant to be interoperable. @@ -100,12 +98,10 @@ is meant to be interoperable. .. automethod:: DeviceManagerADB.devices DeviceManagerSUT implementation -------------------------------- +``````````````````````````````` .. autoclass:: mozdevice.DeviceManagerSUT -SUT-specific methods -```````````````````` DeviceManagerSUT has several methods that are only used in specific tests and are not present in all DeviceManager implementations. Please do not use them in code that is meant to be interoperable. @@ -114,7 +110,7 @@ do not use them in code that is meant to be interoperable. .. automethod:: DeviceManagerSUT.adjustResolution Android extensions ------------------- +`````````````````` For Android, we provide two variants of the `DeviceManager` interface with extensions useful for that platform. These classes are called @@ -128,6 +124,8 @@ and DeviceManagerSUT. Here is the interface for DroidADB: These methods are also found in the DroidSUT class. +.. _ADB: + ADB Interface ------------- From ade99b6c8a6899964cffe3afdcfefbb8ebceea98 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Fri, 15 Aug 2014 13:13:14 -0400 Subject: [PATCH 37/86] Backed out changeset 2322a7c26246 (bug 1049501) for Windows bustage. --- content/media/gmp/GMPVideoEncoderParent.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/content/media/gmp/GMPVideoEncoderParent.cpp b/content/media/gmp/GMPVideoEncoderParent.cpp index f352945aead5..816a40cc8b8f 100644 --- a/content/media/gmp/GMPVideoEncoderParent.cpp +++ b/content/media/gmp/GMPVideoEncoderParent.cpp @@ -12,7 +12,6 @@ #include "nsAutoRef.h" #include "GMPParent.h" #include "mozilla/gmp/GMPTypes.h" -#include "nsThread.h" #include "nsThreadUtils.h" #include "runnable_utils.h" @@ -73,9 +72,7 @@ GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin) GMPVideoEncoderParent::~GMPVideoEncoderParent() { - if (mEncodedThread) { - mEncodedThread->Shutdown(); - } + mEncodedThread->Shutdown(); } GMPVideoHostImpl& @@ -241,12 +238,6 @@ GMPVideoEncoderParent::Shutdown() } } -static void -ShutdownEncodedThread(nsCOMPtr& aThread) -{ - aThread->Shutdown(); -} - // Note: Keep this sync'd up with Shutdown void GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) @@ -258,15 +249,6 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) mCallback->Terminated(); mCallback = nullptr; } - // Must be shut down before VideoEncoderDestroyed(), since this can recurse - // the GMPThread event loop. See bug 1049501 - if (mEncodedThread) { - // Can't get it to allow me to use WrapRunnable with a nsCOMPtr() - NS_DispatchToMainThread( - WrapRunnableNM >(&ShutdownEncodedThread, mEncodedThread)); - mEncodedThread = nullptr; - } if (mPlugin) { // Ignore any return code. It is OK for this to fail without killing the process. mPlugin->VideoEncoderDestroyed(this); From ebabae71e7a840da9a5457fdfac0b7ea392e46b3 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Fri, 15 Aug 2014 13:14:03 -0400 Subject: [PATCH 38/86] Backed out changesets 9329fb07c373 and ff8dc9ac0228 (bug 1022501) for Windows mochitest-1 failures. CLOSED TREE --HG-- rename : content/media/fmp4/eme/EMEAudioDecoder.cpp => content/media/fmp4/eme/EMEAACDecoder.cpp rename : content/media/fmp4/eme/EMEAudioDecoder.h => content/media/fmp4/eme/EMEAACDecoder.h rename : content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp => content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp rename : content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h => content/media/fmp4/ffmpeg/FFmpegAACDecoder.h --- content/media/DecoderTraits.cpp | 3 +- content/media/fmp4/BlankDecoderModule.cpp | 13 +--- content/media/fmp4/MP4Reader.cpp | 27 +++---- content/media/fmp4/MP4Reader.h | 1 - content/media/fmp4/PlatformDecoderModule.cpp | 6 -- content/media/fmp4/PlatformDecoderModule.h | 17 ++--- content/media/fmp4/apple/AppleATDecoder.cpp | 20 ++--- content/media/fmp4/apple/AppleATDecoder.h | 1 - .../media/fmp4/apple/AppleDecoderModule.cpp | 12 +-- content/media/fmp4/apple/AppleDecoderModule.h | 8 +- ...{EMEAudioDecoder.cpp => EMEAACDecoder.cpp} | 60 +++++++-------- .../{EMEAudioDecoder.h => EMEAACDecoder.h} | 24 +++--- content/media/fmp4/eme/EMEDecoderModule.cpp | 22 +++--- content/media/fmp4/eme/EMEDecoderModule.h | 6 +- content/media/fmp4/eme/moz.build | 4 +- ...gAudioDecoder.cpp => FFmpegAACDecoder.cpp} | 73 +++++-------------- ...FmpegAudioDecoder.h => FFmpegAACDecoder.h} | 13 ++-- .../media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 6 +- .../media/fmp4/ffmpeg/FFmpegDecoderModule.h | 15 ++-- content/media/fmp4/ffmpeg/FFmpegLibs.h | 2 - content/media/fmp4/ffmpeg/libav53/moz.build | 2 +- content/media/fmp4/ffmpeg/libav54/moz.build | 2 +- content/media/fmp4/ffmpeg/libav55/moz.build | 2 +- content/media/fmp4/gonk/GonkDecoderModule.cpp | 6 +- content/media/fmp4/gonk/GonkDecoderModule.h | 6 +- content/media/fmp4/wmf/WMFDecoderModule.cpp | 6 +- content/media/fmp4/wmf/WMFDecoderModule.h | 6 +- media/libstagefright/binding/DecoderData.cpp | 3 +- media/libstagefright/binding/mp4_demuxer.cpp | 11 +-- .../media/libstagefright/MPEG4Extractor.cpp | 5 +- 30 files changed, 146 insertions(+), 236 deletions(-) rename content/media/fmp4/eme/{EMEAudioDecoder.cpp => EMEAACDecoder.cpp} (84%) rename content/media/fmp4/eme/{EMEAudioDecoder.h => EMEAACDecoder.h} (85%) rename content/media/fmp4/ffmpeg/{FFmpegAudioDecoder.cpp => FFmpegAACDecoder.cpp} (54%) rename content/media/fmp4/ffmpeg/{FFmpegAudioDecoder.h => FFmpegAACDecoder.h} (68%) diff --git a/content/media/DecoderTraits.cpp b/content/media/DecoderTraits.cpp index a4e535a9afa5..30e5db2b80a1 100644 --- a/content/media/DecoderTraits.cpp +++ b/content/media/DecoderTraits.cpp @@ -441,8 +441,7 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType, } #endif #ifdef MOZ_WMF - if (Preferences::GetBool("media.fragmented-mp4.exposed", false) && - IsWMFSupportedType(nsDependentCString(aMIMEType))) { + if (IsWMFSupportedType(nsDependentCString(aMIMEType))) { if (!aHaveRequestedCodecs) { return CANPLAY_MAYBE; } diff --git a/content/media/fmp4/BlankDecoderModule.cpp b/content/media/fmp4/BlankDecoderModule.cpp index 25d8b63311e9..637d8fdf2673 100644 --- a/content/media/fmp4/BlankDecoderModule.cpp +++ b/content/media/fmp4/BlankDecoderModule.cpp @@ -229,9 +229,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { BlankAudioDataCreator* creator = new BlankAudioDataCreator( aConfig.channel_count, aConfig.samples_per_second); @@ -241,13 +241,6 @@ public: aCallback); return decoder.forget(); } - - virtual bool - SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE - { - return true; - } - }; PlatformDecoderModule* CreateBlankDecoderModule() diff --git a/content/media/fmp4/MP4Reader.cpp b/content/media/fmp4/MP4Reader.cpp index 7341564fccfe..5f2f536ffa45 100644 --- a/content/media/fmp4/MP4Reader.cpp +++ b/content/media/fmp4/MP4Reader.cpp @@ -288,14 +288,6 @@ MP4Reader::ExtractCryptoInitData(nsTArray& aInitData) } } -bool -MP4Reader::IsSupportedAudioMimeType(const char* aMimeType) -{ - return (!strcmp(aMimeType, "audio/mpeg") || - !strcmp(aMimeType, "audio/mp4a-latm")) && - mPlatform->SupportsAudioMimeType(aMimeType); -} - nsresult MP4Reader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) @@ -304,6 +296,13 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, bool ok = mDemuxer->Init(); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); + mInfo.mAudio.mHasAudio = mAudio.mActive = mDemuxer->HasValidAudio(); + const AudioDecoderConfig& audio = mDemuxer->AudioConfig(); + // If we have audio, we *only* allow AAC to be decoded. + if (mInfo.mAudio.mHasAudio && strcmp(audio.mime_type, "audio/mp4a-latm")) { + return NS_ERROR_FAILURE; + } + mInfo.mVideo.mHasVideo = mVideo.mActive = mDemuxer->HasValidVideo(); const VideoDecoderConfig& video = mDemuxer->VideoConfig(); // If we have video, we *only* allow H.264 to be decoded. @@ -371,18 +370,14 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE); } - if (mDemuxer->HasValidAudio()) { + if (HasAudio()) { const AudioDecoderConfig& audio = mDemuxer->AudioConfig(); - mInfo.mAudio.mHasAudio = mAudio.mActive = true; - if (mInfo.mAudio.mHasAudio && !IsSupportedAudioMimeType(audio.mime_type)) { - return NS_ERROR_FAILURE; - } mInfo.mAudio.mRate = audio.samples_per_second; mInfo.mAudio.mChannels = audio.channel_count; mAudio.mCallback = new DecoderCallback(this, kAudio); - mAudio.mDecoder = mPlatform->CreateAudioDecoder(audio, - mAudio.mTaskQueue, - mAudio.mCallback); + mAudio.mDecoder = mPlatform->CreateAACDecoder(audio, + mAudio.mTaskQueue, + mAudio.mCallback); NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE); nsresult rv = mAudio.mDecoder->Init(); NS_ENSURE_SUCCESS(rv, rv); diff --git a/content/media/fmp4/MP4Reader.h b/content/media/fmp4/MP4Reader.h index 6fa9cbe2278d..6bc00ad18b31 100644 --- a/content/media/fmp4/MP4Reader.h +++ b/content/media/fmp4/MP4Reader.h @@ -87,7 +87,6 @@ private: void Flush(mp4_demuxer::TrackType aTrack); void DrainComplete(mp4_demuxer::TrackType aTrack); void UpdateIndex(); - bool IsSupportedAudioMimeType(const char* aMimeType); void NotifyResourcesStatusChanged(); bool IsWaitingOnCodecResource(); bool IsWaitingOnCDMResource(); diff --git a/content/media/fmp4/PlatformDecoderModule.cpp b/content/media/fmp4/PlatformDecoderModule.cpp index cd145b5a6ad0..c19b03bceedc 100644 --- a/content/media/fmp4/PlatformDecoderModule.cpp +++ b/content/media/fmp4/PlatformDecoderModule.cpp @@ -153,10 +153,4 @@ PlatformDecoderModule::Create() return nullptr; } -bool -PlatformDecoderModule::SupportsAudioMimeType(const char* aMimeType) -{ - return !strcmp(aMimeType, "audio/mp4a-latm"); -} - } // namespace mozilla diff --git a/content/media/fmp4/PlatformDecoderModule.h b/content/media/fmp4/PlatformDecoderModule.h index d8bf178eafd0..9c677139a8e5 100644 --- a/content/media/fmp4/PlatformDecoderModule.h +++ b/content/media/fmp4/PlatformDecoderModule.h @@ -35,8 +35,8 @@ class CDMProxy; typedef int64_t Microseconds; // The PlatformDecoderModule interface is used by the MP4Reader to abstract -// access to the H264 and Audio (AAC/MP3) decoders provided by various platforms. -// It may be extended to support other codecs in future. Each platform (Windows, +// access to the H264 and AAC decoders provided by various platforms. It +// may be extended to support other codecs in future. Each platform (Windows, // MacOSX, Linux, B2G etc) must implement a PlatformDecoderModule to provide // access to its decoders in order to get decompressed H.264/AAC from the // MP4Reader. @@ -103,7 +103,7 @@ public: MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback) = 0; - // Creates an Audio decoder with the specified properties. + // Creates an AAC decoder with the specified properties. // Asynchronous decoding of audio should be done in runnables dispatched to // aAudioTaskQueue. If the task queue isn't needed, the decoder should // not hold a reference to it. @@ -114,14 +114,9 @@ public: // It is safe to store a reference to aConfig. // This is called on the decode task queue. virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) = 0; - - // An audio decoder module must support AAC by default. - // If more audio codec is to be supported, SupportsAudioMimeType will have - // to be extended - virtual bool SupportsAudioMimeType(const char* aMimeType); + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) = 0; virtual ~PlatformDecoderModule() {} diff --git a/content/media/fmp4/apple/AppleATDecoder.cpp b/content/media/fmp4/apple/AppleATDecoder.cpp index 666261505cf7..597328473052 100644 --- a/content/media/fmp4/apple/AppleATDecoder.cpp +++ b/content/media/fmp4/apple/AppleATDecoder.cpp @@ -37,20 +37,13 @@ AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, , mHaveOutput(false) { MOZ_COUNT_CTOR(AppleATDecoder); - LOG("Creating Apple AudioToolbox Audio decoder"); + LOG("Creating Apple AudioToolbox AAC decoder"); LOG("Audio Decoder configuration: %s %d Hz %d channels %d bits per channel", mConfig.mime_type, mConfig.samples_per_second, mConfig.channel_count, mConfig.bits_per_sample); - - if (!strcmp(aConfig.mime_type, "audio/mpeg")) { - mFileType = kAudioFileMP3Type; - } else if (!strcmp(aConfig.mime_type, "audio/mp4a-latm")) { - mFileType = kAudioFileAAC_ADTSType; - } else { - mFileType = 0; - } + // TODO: Verify aConfig.mime_type. } AppleATDecoder::~AppleATDecoder() @@ -87,15 +80,12 @@ _SampleCallback(void* aDecoder, nsresult AppleATDecoder::Init() { - if (!mFileType) { - NS_ERROR("Non recognised format"); - return NS_ERROR_FAILURE; - } - LOG("Initializing Apple AudioToolbox Audio decoder"); + LOG("Initializing Apple AudioToolbox AAC decoder"); + AudioFileTypeID fileType = kAudioFileAAC_ADTSType; OSStatus rv = AudioFileStreamOpen(this, _MetadataCallback, _SampleCallback, - mFileType, + fileType, &mStream); if (rv) { NS_ERROR("Couldn't open AudioFileStream"); diff --git a/content/media/fmp4/apple/AppleATDecoder.h b/content/media/fmp4/apple/AppleATDecoder.h index 6c84a9076633..b236a1974d96 100644 --- a/content/media/fmp4/apple/AppleATDecoder.h +++ b/content/media/fmp4/apple/AppleATDecoder.h @@ -53,7 +53,6 @@ private: int64_t mSamplePosition; bool mHaveOutput; AudioStreamBasicDescription mOutputFormat; - AudioFileTypeID mFileType; void SetupDecoder(); void SubmitSample(nsAutoPtr aSample); diff --git a/content/media/fmp4/apple/AppleDecoderModule.cpp b/content/media/fmp4/apple/AppleDecoderModule.cpp index fc4919c7fa66..eb037bae9152 100644 --- a/content/media/fmp4/apple/AppleDecoderModule.cpp +++ b/content/media/fmp4/apple/AppleDecoderModule.cpp @@ -87,19 +87,13 @@ AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCo } already_AddRefed -AppleDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback); return decoder.forget(); } -bool -AppleDecoderModule::SupportsAudioMimeType(const char* aMimeType) -{ - return !strcmp(aMimeType, "audio/mp4a-latm") || !strcmp(aMimeType, "audio/mpeg"); -} - } // namespace mozilla diff --git a/content/media/fmp4/apple/AppleDecoderModule.h b/content/media/fmp4/apple/AppleDecoderModule.h index 639ec8a730e6..21943f808eec 100644 --- a/content/media/fmp4/apple/AppleDecoderModule.h +++ b/content/media/fmp4/apple/AppleDecoderModule.h @@ -34,11 +34,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; - - virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE; + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; static void Init(); private: diff --git a/content/media/fmp4/eme/EMEAudioDecoder.cpp b/content/media/fmp4/eme/EMEAACDecoder.cpp similarity index 84% rename from content/media/fmp4/eme/EMEAudioDecoder.cpp rename to content/media/fmp4/eme/EMEAACDecoder.cpp index 94aec13b8a27..fa32b5e1395a 100644 --- a/content/media/fmp4/eme/EMEAudioDecoder.cpp +++ b/content/media/fmp4/eme/EMEAACDecoder.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "EMEAudioDecoder.h" +#include "EMEAACDecoder.h" #include "mp4_demuxer/DecoderData.h" #include "mozilla/EMELog.h" #include "gmp-audio-host.h" @@ -18,10 +18,10 @@ namespace mozilla { -EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy, - const AudioDecoderConfig& aConfig, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback) +EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy, + const AudioDecoderConfig& aConfig, + MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback) : mAudioRate(0) , mAudioBytesPerSample(0) , mAudioChannels(0) @@ -34,17 +34,17 @@ EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy, , mConfig(aConfig) , mTaskQueue(aTaskQueue) , mCallback(aCallback) - , mMonitor("EMEAudioDecoder") + , mMonitor("EMEAACDecoder") , mFlushComplete(false) { } -EMEAudioDecoder::~EMEAudioDecoder() +EMEAACDecoder::~EMEAACDecoder() { } nsresult -EMEAudioDecoder::Init() +EMEAACDecoder::Init() { // Note: this runs on the decode task queue. @@ -65,7 +65,7 @@ EMEAudioDecoder::Init() } nsresult -EMEAudioDecoder::Input(MP4Sample* aSample) +EMEAACDecoder::Input(MP4Sample* aSample) { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. @@ -77,7 +77,7 @@ EMEAudioDecoder::Input(MP4Sample* aSample) } nsresult -EMEAudioDecoder::Flush() +EMEAACDecoder::Flush() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. @@ -87,7 +87,7 @@ EMEAudioDecoder::Flush() } nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpFlush); + task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpFlush); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); @@ -102,34 +102,34 @@ EMEAudioDecoder::Flush() } nsresult -EMEAudioDecoder::Drain() +EMEAACDecoder::Drain() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpDrain); + task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpDrain); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult -EMEAudioDecoder::Shutdown() +EMEAACDecoder::Shutdown() { MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue. nsRefPtr task; - task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpShutdown); + task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpShutdown); nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } void -EMEAudioDecoder::Decoded(const nsTArray& aPCM, - uint64_t aTimeStamp, - uint32_t aChannels, - uint32_t aRate) +EMEAACDecoder::Decoded(const nsTArray& aPCM, + uint64_t aTimeStamp, + uint32_t aChannels, + uint32_t aRate) { MOZ_ASSERT(IsOnGMPThread()); @@ -192,21 +192,21 @@ EMEAudioDecoder::Decoded(const nsTArray& aPCM, } void -EMEAudioDecoder::InputDataExhausted() +EMEAACDecoder::InputDataExhausted() { MOZ_ASSERT(IsOnGMPThread()); mCallback->InputExhausted(); } void -EMEAudioDecoder::DrainComplete() +EMEAACDecoder::DrainComplete() { MOZ_ASSERT(IsOnGMPThread()); mCallback->DrainComplete(); } void -EMEAudioDecoder::ResetComplete() +EMEAACDecoder::ResetComplete() { MOZ_ASSERT(IsOnGMPThread()); mMustRecaptureAudioPosition = true; @@ -218,23 +218,23 @@ EMEAudioDecoder::ResetComplete() } void -EMEAudioDecoder::Error(GMPErr aErr) +EMEAACDecoder::Error(GMPErr aErr) { MOZ_ASSERT(IsOnGMPThread()); - EME_LOG("EMEAudioDecoder::Error"); + EME_LOG("EMEAACDecoder::Error"); mCallback->Error(); GmpShutdown(); } void -EMEAudioDecoder::Terminated() +EMEAACDecoder::Terminated() { MOZ_ASSERT(IsOnGMPThread()); GmpShutdown(); } nsresult -EMEAudioDecoder::GmpInit() +EMEAACDecoder::GmpInit() { MOZ_ASSERT(IsOnGMPThread()); @@ -266,7 +266,7 @@ EMEAudioDecoder::GmpInit() } nsresult -EMEAudioDecoder::GmpInput(MP4Sample* aSample) +EMEAACDecoder::GmpInput(MP4Sample* aSample) { MOZ_ASSERT(IsOnGMPThread()); nsAutoPtr sample(aSample); @@ -296,7 +296,7 @@ EMEAudioDecoder::GmpInput(MP4Sample* aSample) } void -EMEAudioDecoder::GmpFlush() +EMEAACDecoder::GmpFlush() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP || NS_FAILED(mGMP->Reset())) { @@ -308,7 +308,7 @@ EMEAudioDecoder::GmpFlush() } void -EMEAudioDecoder::GmpDrain() +EMEAACDecoder::GmpDrain() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP || NS_FAILED(mGMP->Drain())) { @@ -317,7 +317,7 @@ EMEAudioDecoder::GmpDrain() } void -EMEAudioDecoder::GmpShutdown() +EMEAACDecoder::GmpShutdown() { MOZ_ASSERT(IsOnGMPThread()); if (!mGMP) { diff --git a/content/media/fmp4/eme/EMEAudioDecoder.h b/content/media/fmp4/eme/EMEAACDecoder.h similarity index 85% rename from content/media/fmp4/eme/EMEAudioDecoder.h rename to content/media/fmp4/eme/EMEAACDecoder.h index 2d4bcb7b857d..9232cdbaa92e 100644 --- a/content/media/fmp4/eme/EMEAudioDecoder.h +++ b/content/media/fmp4/eme/EMEAACDecoder.h @@ -16,18 +16,18 @@ namespace mozilla { -class EMEAudioDecoder : public MediaDataDecoder - , public GMPAudioDecoderProxyCallback +class EMEAACDecoder : public MediaDataDecoder + , public GMPAudioDecoderProxyCallback { typedef mp4_demuxer::MP4Sample MP4Sample; typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig; public: - EMEAudioDecoder(CDMProxy* aProxy, - const AudioDecoderConfig& aConfig, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback); + EMEAACDecoder(CDMProxy* aProxy, + const AudioDecoderConfig& aConfig, + MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback); - ~EMEAudioDecoder(); + ~EMEAACDecoder(); // MediaDataDecoder implementation. virtual nsresult Init() MOZ_OVERRIDE; @@ -51,7 +51,7 @@ private: class DeliverSample : public nsRunnable { public: - DeliverSample(EMEAudioDecoder* aDecoder, + DeliverSample(EMEAACDecoder* aDecoder, mp4_demuxer::MP4Sample* aSample) : mDecoder(aDecoder) , mSample(aSample) @@ -62,13 +62,13 @@ private: return NS_OK; } private: - nsRefPtr mDecoder; + nsRefPtr mDecoder; nsAutoPtr mSample; }; class InitTask : public nsRunnable { public: - InitTask(EMEAudioDecoder* aDecoder) + InitTask(EMEAACDecoder* aDecoder) : mDecoder(aDecoder) {} NS_IMETHOD Run() { @@ -76,7 +76,7 @@ private: return NS_OK; } nsresult mResult; - EMEAudioDecoder* mDecoder; + EMEAACDecoder* mDecoder; }; nsresult GmpInit(); @@ -114,4 +114,4 @@ private: } // namespace mozilla -#endif +#endif \ No newline at end of file diff --git a/content/media/fmp4/eme/EMEDecoderModule.cpp b/content/media/fmp4/eme/EMEDecoderModule.cpp index 968e12d90b0b..65c6d9f555c4 100644 --- a/content/media/fmp4/eme/EMEDecoderModule.cpp +++ b/content/media/fmp4/eme/EMEDecoderModule.cpp @@ -19,7 +19,7 @@ #include "SharedThreadPool.h" #include "mozilla/EMELog.h" #include "EMEH264Decoder.h" -#include "EMEAudioDecoder.h" +#include "EMEAACDecoder.h" #include namespace mozilla { @@ -227,21 +227,21 @@ EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig, } already_AddRefed -EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { if (mCDMDecodesAudio) { - nsRefPtr decoder(new EMEAudioDecoder(mProxy, - aConfig, - aAudioTaskQueue, - aCallback)); + nsRefPtr decoder(new EMEAACDecoder(mProxy, + aConfig, + aAudioTaskQueue, + aCallback)); return decoder.forget(); } - nsRefPtr decoder(mPDM->CreateAudioDecoder(aConfig, - aAudioTaskQueue, - aCallback)); + nsRefPtr decoder(mPDM->CreateAACDecoder(aConfig, + aAudioTaskQueue, + aCallback)); if (!decoder) { return nullptr; } diff --git a/content/media/fmp4/eme/EMEDecoderModule.h b/content/media/fmp4/eme/EMEDecoderModule.h index 89ec4597ec9e..afe0212f35be 100644 --- a/content/media/fmp4/eme/EMEDecoderModule.h +++ b/content/media/fmp4/eme/EMEDecoderModule.h @@ -42,9 +42,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; private: nsRefPtr mProxy; diff --git a/content/media/fmp4/eme/moz.build b/content/media/fmp4/eme/moz.build index 19f484899fa0..d22505cf61f5 100644 --- a/content/media/fmp4/eme/moz.build +++ b/content/media/fmp4/eme/moz.build @@ -5,13 +5,13 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS += [ - 'EMEAudioDecoder.h', + 'EMEAACDecoder.h', 'EMEDecoderModule.h', 'EMEH264Decoder.h', ] UNIFIED_SOURCES += [ - 'EMEAudioDecoder.cpp', + 'EMEAACDecoder.cpp', 'EMEDecoderModule.cpp', 'EMEH264Decoder.cpp', ] diff --git a/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp similarity index 54% rename from content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp rename to content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp index fcac1b13144f..4c224b5583e2 100644 --- a/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp @@ -7,7 +7,7 @@ #include "MediaTaskQueue.h" #include "FFmpegRuntimeLinker.h" -#include "FFmpegAudioDecoder.h" +#include "FFmpegAACDecoder.h" #define MAX_CHANNELS 16 @@ -16,17 +16,16 @@ typedef mp4_demuxer::MP4Sample MP4Sample; namespace mozilla { -FFmpegAudioDecoder::FFmpegAudioDecoder( +FFmpegAACDecoder::FFmpegAACDecoder( MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, const mp4_demuxer::AudioDecoderConfig& aConfig) - : FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mime_type)) - , mCallback(aCallback) + : FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_AAC), mCallback(aCallback) { - MOZ_COUNT_CTOR(FFmpegAudioDecoder); + MOZ_COUNT_CTOR(FFmpegAACDecoder); } nsresult -FFmpegAudioDecoder::Init() +FFmpegAACDecoder::Init() { nsresult rv = FFmpegDataDecoder::Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -35,44 +34,24 @@ FFmpegAudioDecoder::Init() } static AudioDataValue* -CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames) +CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples) { MOZ_ASSERT(aNumChannels <= MAX_CHANNELS); nsAutoArrayPtr audio( - new AudioDataValue[aNumChannels * aNumAFrames]); + new AudioDataValue[aNumChannels * aNumSamples]); + + AudioDataValue** data = reinterpret_cast(aFrame->data); if (aFrame->format == AV_SAMPLE_FMT_FLT) { // Audio data already packed. No need to do anything other than copy it // into a buffer we own. - memcpy(audio, aFrame->data[0], - aNumChannels * aNumAFrames * sizeof(AudioDataValue)); + memcpy(audio, data[0], aNumChannels * aNumSamples * sizeof(AudioDataValue)); } else if (aFrame->format == AV_SAMPLE_FMT_FLTP) { // Planar audio data. Pack it into something we can understand. - AudioDataValue* tmp = audio; - AudioDataValue** data = reinterpret_cast(aFrame->data); - for (uint32_t frame = 0; frame < aNumAFrames; frame++) { - for (uint32_t channel = 0; channel < aNumChannels; channel++) { - *tmp++ = data[channel][frame]; - } - } - } else if (aFrame->format == AV_SAMPLE_FMT_S16) { - // Audio data already packed. Need to convert from S16 to 32 bits Float - AudioDataValue* tmp = audio; - int16_t* data = reinterpret_cast(aFrame->data)[0]; - for (uint32_t frame = 0; frame < aNumAFrames; frame++) { - for (uint32_t channel = 0; channel < aNumChannels; channel++) { - *tmp++ = AudioSampleToFloat(*data++); - } - } - } else if (aFrame->format == AV_SAMPLE_FMT_S16P) { - // Planar audio data. Convert it from S16 to 32 bits float - // and pack it into something we can understand. - AudioDataValue* tmp = audio; - int16_t** data = reinterpret_cast(aFrame->data); - for (uint32_t frame = 0; frame < aNumAFrames; frame++) { - for (uint32_t channel = 0; channel < aNumChannels; channel++) { - *tmp++ = AudioSampleToFloat(data[channel][frame]); + for (uint32_t channel = 0; channel < aNumChannels; channel++) { + for (uint32_t sample = 0; sample < aNumSamples; sample++) { + audio[sample * aNumChannels + channel] = data[channel][sample]; } } } @@ -81,7 +60,7 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames) } void -FFmpegAudioDecoder::DecodePacket(MP4Sample* aSample) +FFmpegAACDecoder::DecodePacket(MP4Sample* aSample) { AVPacket packet; av_init_packet(&packet); @@ -128,38 +107,24 @@ FFmpegAudioDecoder::DecodePacket(MP4Sample* aSample) } nsresult -FFmpegAudioDecoder::Input(MP4Sample* aSample) +FFmpegAACDecoder::Input(MP4Sample* aSample) { mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg >( - this, &FFmpegAudioDecoder::DecodePacket, nsAutoPtr(aSample))); + this, &FFmpegAACDecoder::DecodePacket, nsAutoPtr(aSample))); return NS_OK; } nsresult -FFmpegAudioDecoder::Drain() +FFmpegAACDecoder::Drain() { mCallback->DrainComplete(); return NS_OK; } -AVCodecID -FFmpegAudioDecoder::GetCodecId(const char* aMimeType) +FFmpegAACDecoder::~FFmpegAACDecoder() { - if (!strcmp(aMimeType, "audio/mpeg")) { - return AV_CODEC_ID_MP3; - } - - if (!strcmp(aMimeType, "audio/mp4a-latm")) { - return AV_CODEC_ID_AAC; - } - - return AV_CODEC_ID_NONE; -} - -FFmpegAudioDecoder::~FFmpegAudioDecoder() -{ - MOZ_COUNT_DTOR(FFmpegAudioDecoder); + MOZ_COUNT_DTOR(FFmpegAACDecoder); } } // namespace mozilla diff --git a/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.h similarity index 68% rename from content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h rename to content/media/fmp4/ffmpeg/FFmpegAACDecoder.h index 9f7bfa6b9ad1..446a4082f142 100644 --- a/content/media/fmp4/ffmpeg/FFmpegAudioDecoder.h +++ b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.h @@ -13,23 +13,22 @@ namespace mozilla { -template class FFmpegAudioDecoder +template class FFmpegAACDecoder { }; template <> -class FFmpegAudioDecoder : public FFmpegDataDecoder +class FFmpegAACDecoder : public FFmpegDataDecoder { public: - FFmpegAudioDecoder(MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallback* aCallback, - const mp4_demuxer::AudioDecoderConfig& aConfig); - virtual ~FFmpegAudioDecoder(); + FFmpegAACDecoder(MediaTaskQueue* aTaskQueue, + MediaDataDecoderCallback* aCallback, + const mp4_demuxer::AudioDecoderConfig& aConfig); + virtual ~FFmpegAACDecoder(); virtual nsresult Init() MOZ_OVERRIDE; virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE; virtual nsresult Drain() MOZ_OVERRIDE; - static AVCodecID GetCodecId(const char* aMimeType); private: void DecodePacket(mp4_demuxer::MP4Sample* aSample); diff --git a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index 89fdc3ec25e6..1388c8808593 100644 --- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -108,10 +108,8 @@ FFmpegDataDecoder::Init() if (mCodecContext->codec_type == AVMEDIA_TYPE_AUDIO && mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT && - mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP && - mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 && - mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16P) { - NS_WARNING("FFmpeg audio decoder outputs unsupported audio format."); + mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP) { + NS_WARNING("FFmpeg AAC decoder outputs unsupported audio format."); return NS_ERROR_FAILURE; } diff --git a/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h b/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h index 6f54f18fb27b..b3f9bf9161c2 100644 --- a/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h +++ b/content/media/fmp4/ffmpeg/FFmpegDecoderModule.h @@ -8,7 +8,7 @@ #define __FFmpegDecoderModule_h__ #include "PlatformDecoderModule.h" -#include "FFmpegAudioDecoder.h" +#include "FFmpegAACDecoder.h" #include "FFmpegH264Decoder.h" namespace mozilla @@ -39,19 +39,14 @@ public: } virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE { nsRefPtr decoder = - new FFmpegAudioDecoder(aAudioTaskQueue, aCallback, aConfig); + new FFmpegAACDecoder(aAudioTaskQueue, aCallback, aConfig); return decoder.forget(); } - - virtual bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE - { - return FFmpegAudioDecoder::GetCodecId(aMimeType) != AV_CODEC_ID_NONE; - } }; } // namespace mozilla diff --git a/content/media/fmp4/ffmpeg/FFmpegLibs.h b/content/media/fmp4/ffmpeg/FFmpegLibs.h index aad71552f210..22050d58860f 100644 --- a/content/media/fmp4/ffmpeg/FFmpegLibs.h +++ b/content/media/fmp4/ffmpeg/FFmpegLibs.h @@ -18,8 +18,6 @@ extern "C" { #if LIBAVCODEC_VERSION_MAJOR < 55 #define AV_CODEC_ID_H264 CODEC_ID_H264 #define AV_CODEC_ID_AAC CODEC_ID_AAC -#define AV_CODEC_ID_MP3 CODEC_ID_MP3 -#define AV_CODEC_ID_NONE CODEC_ID_NONE typedef CodecID AVCodecID; #endif diff --git a/content/media/fmp4/ffmpeg/libav53/moz.build b/content/media/fmp4/ffmpeg/libav53/moz.build index d9053cff4a1e..25650064b756 100644 --- a/content/media/fmp4/ffmpeg/libav53/moz.build +++ b/content/media/fmp4/ffmpeg/libav53/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAudioDecoder.cpp', + '../FFmpegAACDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/ffmpeg/libav54/moz.build b/content/media/fmp4/ffmpeg/libav54/moz.build index d9053cff4a1e..25650064b756 100644 --- a/content/media/fmp4/ffmpeg/libav54/moz.build +++ b/content/media/fmp4/ffmpeg/libav54/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAudioDecoder.cpp', + '../FFmpegAACDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/ffmpeg/libav55/moz.build b/content/media/fmp4/ffmpeg/libav55/moz.build index 5d48e219aef8..234f4e24fe01 100644 --- a/content/media/fmp4/ffmpeg/libav55/moz.build +++ b/content/media/fmp4/ffmpeg/libav55/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ - '../FFmpegAudioDecoder.cpp', + '../FFmpegAACDecoder.cpp', '../FFmpegDataDecoder.cpp', '../FFmpegDecoderModule.cpp', '../FFmpegH264Decoder.cpp', diff --git a/content/media/fmp4/gonk/GonkDecoderModule.cpp b/content/media/fmp4/gonk/GonkDecoderModule.cpp index d1f739da6e1d..022fd3035051 100644 --- a/content/media/fmp4/gonk/GonkDecoderModule.cpp +++ b/content/media/fmp4/gonk/GonkDecoderModule.cpp @@ -48,9 +48,9 @@ GonkDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aCon } already_AddRefed -GonkDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +GonkDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig), aAudioTaskQueue, diff --git a/content/media/fmp4/gonk/GonkDecoderModule.h b/content/media/fmp4/gonk/GonkDecoderModule.h index edda66f4d086..95c0e08a4cf5 100644 --- a/content/media/fmp4/gonk/GonkDecoderModule.h +++ b/content/media/fmp4/gonk/GonkDecoderModule.h @@ -29,9 +29,9 @@ public: // Decode thread. virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; static void Init(); }; diff --git a/content/media/fmp4/wmf/WMFDecoderModule.cpp b/content/media/fmp4/wmf/WMFDecoderModule.cpp index 00f390e2fe25..55d3deb38ddd 100644 --- a/content/media/fmp4/wmf/WMFDecoderModule.cpp +++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp @@ -81,9 +81,9 @@ WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConf } already_AddRefed -WMFDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) +WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) { nsRefPtr decoder = new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig), diff --git a/content/media/fmp4/wmf/WMFDecoderModule.h b/content/media/fmp4/wmf/WMFDecoderModule.h index b2f2b58e79ee..d92d1281b412 100644 --- a/content/media/fmp4/wmf/WMFDecoderModule.h +++ b/content/media/fmp4/wmf/WMFDecoderModule.h @@ -30,9 +30,9 @@ public: MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; + CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, + MediaTaskQueue* aAudioTaskQueue, + MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE; // Called on main thread. static void Init(); diff --git a/media/libstagefright/binding/DecoderData.cpp b/media/libstagefright/binding/DecoderData.cpp index 69673d4cea7e..32c1d5e1ceff 100644 --- a/media/libstagefright/binding/DecoderData.cpp +++ b/media/libstagefright/binding/DecoderData.cpp @@ -8,7 +8,6 @@ #include "mp4_demuxer/DecoderData.h" #include "media/stagefright/MetaData.h" #include "media/stagefright/MediaBuffer.h" -#include "media/stagefright/MediaDefs.h" #include "media/stagefright/Utils.h" #include "mozilla/ArrayUtils.h" #include "include/ESDS.h" @@ -160,7 +159,7 @@ bool AudioDecoderConfig::IsValid() { return channel_count > 0 && samples_per_second > 0 && frequency_index > 0 && - (mime_type != MEDIA_MIMETYPE_AUDIO_AAC || aac_profile > 0); + aac_profile > 0; } void diff --git a/media/libstagefright/binding/mp4_demuxer.cpp b/media/libstagefright/binding/mp4_demuxer.cpp index c72009094412..5daf7dd75bf9 100644 --- a/media/libstagefright/binding/mp4_demuxer.cpp +++ b/media/libstagefright/binding/mp4_demuxer.cpp @@ -4,7 +4,6 @@ #include "include/MPEG4Extractor.h" #include "media/stagefright/DataSource.h" -#include "media/stagefright/MediaDefs.h" #include "media/stagefright/MediaSource.h" #include "media/stagefright/MetaData.h" #include "mp4_demuxer/Adts.h" @@ -169,12 +168,10 @@ MP4Demuxer::DemuxAudioSample() } sample->Update(); - if (!strcmp(mAudioConfig.mime_type, MEDIA_MIMETYPE_AUDIO_AAC)) { - if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count, - mAudioConfig.frequency_index, - mAudioConfig.aac_profile, sample)) { - return nullptr; - } + if (!Adts::ConvertEsdsToAdts(mAudioConfig.channel_count, + mAudioConfig.frequency_index, + mAudioConfig.aac_profile, sample)) { + return nullptr; } return sample.forget(); diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp index 62811fbe0613..93ac8e5cfe20 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp @@ -2293,7 +2293,10 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( if (objectTypeIndication == 0x6b) { // The media subtype is MP3 audio - mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); + // Our software MP3 audio decoder may not be able to handle + // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED + ALOGE("MP3 track in MP4/3GPP file is not supported"); + return ERROR_UNSUPPORTED; } const uint8_t *csd; From 9a2a60943d8aaa5406dea36f9ded96709a777194 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 13 Aug 2014 17:50:42 -0700 Subject: [PATCH 39/86] Bug 1053616: Remove uses of PR_SetError from mozilla::pkix tests, r=keeler --HG-- extra : rebase_source : 1fc7ce9ab400c39e3c4afb68940be93cc2a0b848 --- security/pkix/test/gtest/nssgtest.h | 1 - security/pkix/test/lib/pkixtestutil.cpp | 17 ----------------- security/pkix/test/lib/pkixtestutil.h | 5 +---- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/security/pkix/test/gtest/nssgtest.h b/security/pkix/test/gtest/nssgtest.h index 59b18ce3610a..b499add65700 100644 --- a/security/pkix/test/gtest/nssgtest.h +++ b/security/pkix/test/gtest/nssgtest.h @@ -29,7 +29,6 @@ #include "gtest/gtest.h" #include "pkix/pkixtypes.h" #include "pkixtestutil.h" -#include "prerror.h" #include "prtime.h" #include "seccomon.h" diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index c60bf305a1c2..cd9e22819de6 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -34,7 +34,6 @@ #include "pkix/pkixnss.h" #include "pkixder.h" #include "pkixutil.h" -#include "prerror.h" #include "prinit.h" #include "prprf.h" #include "secder.h" @@ -67,7 +66,6 @@ OpenFile(const char* dir, const char* filename, const char* mode) ScopedPtr path(new (nothrow) char[strlen(dir) + 1 + strlen(filename) + 1]); if (!path) { - PR_SetError(SEC_ERROR_NO_MEMORY, 0); return nullptr; } strcpy(path.get(), dir); @@ -81,17 +79,12 @@ OpenFile(const char* dir, const char* filename, const char* mode) errno_t error = fopen_s(&rawFile, path.get(), mode); if (error) { // TODO: map error to NSPR error code - PR_SetError(PR_FILE_NOT_FOUND_ERROR, error); rawFile = nullptr; } file = rawFile; } #else file = fopen(path.get(), mode); - if (!file) { - // TODO: map errno to NSPR error code - PR_SetError(PR_FILE_NOT_FOUND_ERROR, errno); - } #endif return file.release(); } @@ -385,7 +378,6 @@ Integer(PLArenaPool* arena, long value) { if (value < 0 || value > 127) { // TODO: add encoding of larger values - PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return nullptr; } @@ -428,7 +420,6 @@ PRTimeToEncodedTime(PLArenaPool* arena, PRTime time, TimeEncoding encoding) if (encoding == UTCTime && (exploded.tm_year < 1950 || exploded.tm_year >= 2050)) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -515,7 +506,6 @@ SignedData(PLArenaPool* arena, const SECItem* tbsData, assert(tbsData); assert(privKey); if (!arena || !tbsData || !privKey) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -596,7 +586,6 @@ Extension(PLArenaPool* arena, SECOidTag extnIDTag, { assert(arena); if (!arena) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -734,7 +723,6 @@ CreateEncodedCertificate(PLArenaPool* arena, long version, assert(issuerNameDER); assert(subjectNameDER); if (!arena || !issuerNameDER || !subjectNameDER) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -795,7 +783,6 @@ TBSCertificate(PLArenaPool* arena, long versionValue, assert(subject); assert(subjectPublicKey); if (!arena || !issuer || !subject || !subjectPublicKey) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -931,7 +918,6 @@ CreateEncodedBasicConstraints(PLArenaPool* arena, bool isCA, { assert(arena); if (!arena) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -965,7 +951,6 @@ CreateEncodedEKUExtension(PLArenaPool* arena, SECOidTag const* ekus, assert(arena); assert(ekus); if (!arena || (!ekus && ekusCount != 0)) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } @@ -990,13 +975,11 @@ SECItem* CreateEncodedOCSPResponse(OCSPResponseContext& context) { if (!context.arena) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } if (!context.skipResponseBytes) { if (!context.signerPrivateKey) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return nullptr; } } diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index b53b1135817c..39a3cc62e16e 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -222,10 +222,7 @@ public: }; // The return value, if non-null, is owned by the arena in the context -// and MUST NOT be freed. -// This function does its best to respect the NSPR error code convention -// (that is, if it returns null, calling PR_GetError() will return the -// error of the failed operation). However, this is not guaranteed. +// and MUST NOT be freed. A null return value indicates an error occurred. SECItem* CreateEncodedOCSPResponse(OCSPResponseContext& context); } } } // namespace mozilla::pkix::test From d08286d3d3eb13b17bfc0572f3df3c0234012b98 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Aug 2014 19:07:26 -0700 Subject: [PATCH 40/86] Bug 1053617: Reduce scope of DER encoding debugging logic to the file it is used in, r=keeler --HG-- extra : rebase_source : c22f7e96dfdd1997626769ac03c6d189321eec1a --- security/pkix/test/lib/pkixtestutil.cpp | 10 +++++++++- security/pkix/test/lib/pkixtestutil.h | 9 --------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index cd9e22819de6..feb1e223b8ab 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -25,6 +25,7 @@ #include "pkixtestutil.h" #include +#include #include #include @@ -53,7 +54,12 @@ deleteCharArray(char* chars) delete[] chars; } -} // unnamed namespace +inline void +fclose_void(FILE* file) { + (void) fclose(file); +} + +typedef mozilla::pkix::ScopedPtr ScopedFILE; FILE* OpenFile(const char* dir, const char* filename, const char* mode) @@ -89,6 +95,8 @@ OpenFile(const char* dir, const char* filename, const char* mode) return file.release(); } +} // unnamed namespace + Result TamperOnce(SECItem& item, const uint8_t* from, size_t fromLen, diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index 39a3cc62e16e..890f8e7cc5bc 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -26,7 +26,6 @@ #define mozilla_pkix_test__pkixtestutils_h #include -#include #include "cert.h" #include "keyhi.h" @@ -49,11 +48,6 @@ public: namespace { -inline void -fclose_void(FILE* file) { - (void) fclose(file); -} - inline void SECITEM_FreeItem_true(SECItem* item) { @@ -64,15 +58,12 @@ SECITEM_FreeItem_true(SECItem* item) typedef ScopedPtr ScopedCERTCertificate; typedef ScopedPtr ScopedCERTCertList; -typedef mozilla::pkix::ScopedPtr ScopedFILE; typedef mozilla::pkix::ScopedPtr ScopedSECItem; typedef mozilla::pkix::ScopedPtr ScopedSECKEYPublicKey; typedef mozilla::pkix::ScopedPtr ScopedSECKEYPrivateKey; -FILE* OpenFile(const char* dir, const char* filename, const char* mode); - extern const PRTime ONE_DAY; // e.g. YMDHMS(2016, 12, 31, 1, 23, 45) => 2016-12-31:01:23:45 (GMT) From 1709415e433b0ebb3726cfe25b3c4d55dfc3cfc2 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Aug 2014 19:12:34 -0700 Subject: [PATCH 41/86] Bug 1053620: Replaces uses of PR_Abort with std::abort in mozilla::pkix, r=keeler --HG-- extra : rebase_source : 2e1f3eec5305e89bfa28fbda856b4e36515a2819 --- security/pkix/test/gtest/nssgtest.cpp | 4 ++-- security/pkix/test/gtest/pkixbuild_tests.cpp | 2 +- .../gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp | 14 +++++++------- security/pkix/test/lib/pkixtestutil.cpp | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/security/pkix/test/gtest/nssgtest.cpp b/security/pkix/test/gtest/nssgtest.cpp index 2b663f1d15ec..e44034ec12e4 100644 --- a/security/pkix/test/gtest/nssgtest.cpp +++ b/security/pkix/test/gtest/nssgtest.cpp @@ -36,7 +36,7 @@ namespace mozilla { namespace pkix { namespace test { NSSTest::SetUpTestCase() { if (NSS_NoDB_Init(nullptr) != SECSuccess) { - PR_Abort(); + abort(); } now = Now(); @@ -49,7 +49,7 @@ NSSTest::NSSTest() : arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) { if (!arena) { - PR_Abort(); + abort(); } } diff --git a/security/pkix/test/gtest/pkixbuild_tests.cpp b/security/pkix/test/gtest/pkixbuild_tests.cpp index b669bd12d88e..c5ee6dee80ee 100644 --- a/security/pkix/test/gtest/pkixbuild_tests.cpp +++ b/security/pkix/test/gtest/pkixbuild_tests.cpp @@ -210,7 +210,7 @@ public: // Initialize the tail of the cert chains we'll be using once, to make the // tests run faster (generating the keys is slow). if (!trustDomain.SetUpCertChainTail()) { - PR_Abort(); + abort(); } } diff --git a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp index e3bdfebfa6c5..e1179a2de287 100644 --- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp +++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp @@ -123,7 +123,7 @@ public: { NSSTest::SetUpTestCase(); if (!SetUpTestCaseInner()) { - PR_Abort(); + abort(); } } @@ -135,7 +135,7 @@ public: // The result of ASCIIToDERName is owned by the arena if (InitInputFromSECItem(ASCIIToDERName(arena.get(), rootName), rootNameDER) != Success) { - PR_Abort(); + abort(); } Input serialNumberDER; @@ -143,17 +143,17 @@ public: if (InitInputFromSECItem( CreateEncodedSerialNumber(arena.get(), ++rootIssuedCount), serialNumberDER) != Success) { - PR_Abort(); + abort(); } Input rootSPKIDER; if (InitInputFromSECItem(rootSPKI.get(), rootSPKIDER) != Success) { - PR_Abort(); + abort(); } endEntityCertID = new (std::nothrow) CertID(rootNameDER, rootSPKIDER, serialNumberDER); if (!endEntityCertID) { - PR_Abort(); + abort(); } } @@ -807,11 +807,11 @@ public: "CN=OCSPGetCertTrustTest Signer", OCSPResponseContext::good, byKey, SEC_OID_OCSP_RESPONDER, &signerCertDER)); if (response.Init(createdResponse) != Success) { - PR_Abort(); + abort(); } if (response.GetLength() == 0 || signerCertDER.GetLength() == 0) { - PR_Abort(); + abort(); } } diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index feb1e223b8ab..6b16fbb46f94 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -223,7 +223,7 @@ private: break; default: PR_NOT_REACHED("EncodeLength: bad lengthLength"); - PR_Abort(); + abort(); } } @@ -293,7 +293,7 @@ HashAlgorithmToLength(SECOidTag hashAlg) return SHA512_LENGTH; default: PR_NOT_REACHED("HashAlgorithmToLength: bad hashAlg"); - PR_Abort(); + abort(); } return 0; } @@ -1416,7 +1416,7 @@ CertStatus(OCSPResponseContext& context) } default: PR_NOT_REACHED("CertStatus: bad context.certStatus"); - PR_Abort(); + abort(); } return nullptr; } From 5a78d0179b6b18aeb32c5e58865cfbc1a74e32e0 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Aug 2014 19:19:29 -0700 Subject: [PATCH 42/86] Bug 1053621: Stop using PR_NOT_REACHED in mozilla::pkix, r=keeler --HG-- extra : rebase_source : b70a3ca2f3dade0439cf902bf4042716e7d1bbd3 --- security/pkix/test/lib/pkixtestutil.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index 6b16fbb46f94..01539b155233 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -222,7 +222,6 @@ private: data[2] = length % 256; break; default: - PR_NOT_REACHED("EncodeLength: bad lengthLength"); abort(); } } @@ -292,7 +291,6 @@ HashAlgorithmToLength(SECOidTag hashAlg) case SEC_OID_SHA512: return SHA512_LENGTH; default: - PR_NOT_REACHED("HashAlgorithmToLength: bad hashAlg"); abort(); } return 0; @@ -1415,8 +1413,8 @@ CertStatus(OCSPResponseContext& context) revocationTime); } default: - PR_NOT_REACHED("CertStatus: bad context.certStatus"); - abort(); + assert(false); + // fall through } return nullptr; } From edb0ac64e02f88902c3eae8c7ff9e18b491e236e Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Aug 2014 19:21:52 -0700 Subject: [PATCH 43/86] Bug 1053627, Part 1: use sizeof instead of PR_ARRAY_SIZE for byte arrays, r=keeler --HG-- extra : rebase_source : a01364ed6b64800142f18d3d350f50ca178ea4bb --- .../pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp | 4 ++-- security/pkix/test/lib/pkixtestutil.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp index e1179a2de287..ec5254c7ba03 100644 --- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp +++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp @@ -634,8 +634,8 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_tampered_eku) SECItem responseSECItem = UnsafeMapInputToSECItem(response); ASSERT_EQ(Success, TamperOnce(responseSECItem, - EKU_SERVER_AUTH, PR_ARRAY_SIZE(EKU_SERVER_AUTH), - EKU_OCSP_SIGNER, PR_ARRAY_SIZE(EKU_OCSP_SIGNER))); + EKU_SERVER_AUTH, sizeof(EKU_SERVER_AUTH), + EKU_OCSP_SIGNER, sizeof(EKU_OCSP_SIGNER))); bool expired; ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT, diff --git a/security/pkix/test/lib/pkixtestutil.cpp b/security/pkix/test/lib/pkixtestutil.cpp index 01539b155233..0157844ea6f5 100644 --- a/security/pkix/test/lib/pkixtestutil.cpp +++ b/security/pkix/test/lib/pkixtestutil.cpp @@ -1052,7 +1052,7 @@ ResponseBytes(OCSPResponseContext& context) SECItem id_pkix_ocsp_basic = { siBuffer, const_cast(id_pkix_ocsp_basic_encoded), - PR_ARRAY_SIZE(id_pkix_ocsp_basic_encoded) + sizeof(id_pkix_ocsp_basic_encoded) }; SECItem* response = BasicOCSPResponse(context); if (!response) { @@ -1110,7 +1110,7 @@ OCSPExtension(OCSPResponseContext& context, OCSPResponseExtension* extension) SECItem critical = { siBuffer, const_cast(trueEncoded), - PR_ARRAY_SIZE(trueEncoded) + sizeof(trueEncoded) }; if (output.Add(&critical) != Success) { return nullptr; From 026854c3f002a7ba32036dddca6e376e3fda459b Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 13 Aug 2014 21:01:35 -0700 Subject: [PATCH 44/86] Bug 1053627, Part 2: Use MOZILLA_PKIX_ARRAY_LENGTH instead of PR_ARRAY_SIZE, r=keeler --HG-- extra : rebase_source : b9ae99d93921cb2f3a8f4395e9240389752fd2de --- security/pkix/test/gtest/pkixbuild_tests.cpp | 7 ++++--- security/pkix/test/lib/pkixtestutil.h | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/security/pkix/test/gtest/pkixbuild_tests.cpp b/security/pkix/test/gtest/pkixbuild_tests.cpp index c5ee6dee80ee..a72aa0ead47a 100644 --- a/security/pkix/test/gtest/pkixbuild_tests.cpp +++ b/security/pkix/test/gtest/pkixbuild_tests.cpp @@ -89,7 +89,8 @@ public: "CN=CA7" }; - static_assert(PR_ARRAY_SIZE(names) == PR_ARRAY_SIZE(certChainTail), + static_assert(MOZILLA_PKIX_ARRAY_LENGTH(names) == + MOZILLA_PKIX_ARRAY_LENGTH(certChainTail), "mismatch in sizes of names and certChainTail arrays"); ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); @@ -97,7 +98,7 @@ public: return false; } - for (size_t i = 0; i < PR_ARRAY_SIZE(names); ++i) { + for (size_t i = 0; i < MOZILLA_PKIX_ARRAY_LENGTH(names); ++i) { const char* issuerName = i == 0 ? names[0] : certChainTail[i - 1]->subjectName; (void) CreateCert(arena.get(), issuerName, names[i], @@ -197,7 +198,7 @@ public: ScopedSECKEYPrivateKey leafCAKey; CERTCertificate* GetLeafCACert() const { - return certChainTail[PR_ARRAY_SIZE(certChainTail) - 1].get(); + return certChainTail[MOZILLA_PKIX_ARRAY_LENGTH(certChainTail) - 1].get(); } }; diff --git a/security/pkix/test/lib/pkixtestutil.h b/security/pkix/test/lib/pkixtestutil.h index 890f8e7cc5bc..f191a4ab0f6e 100644 --- a/security/pkix/test/lib/pkixtestutil.h +++ b/security/pkix/test/lib/pkixtestutil.h @@ -36,6 +36,21 @@ namespace mozilla { namespace pkix { namespace test { +// XXX: Ideally, we should define this instead: +// +// template +// constexpr inline std::size_t +// ArrayLength(T (&)[N]) +// { +// return N; +// } +// +// However, we don't because not all supported compilers support constexpr, +// and we need to calculate array lengths in static_assert sometimes. +// +// XXX: Evaluates its argument twice +#define MOZILLA_PKIX_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) + class TestInput : public Input { public: From 779f8cef59b7e15ffef213470b794f5cbed5e682 Mon Sep 17 00:00:00 2001 From: Susanna Bowen Date: Fri, 15 Aug 2014 10:34:20 -0700 Subject: [PATCH 45/86] Bug 1030993 - Basic reflow implementation for ruby frame classes. r=dbaron To account for spacing between bases or text boxes during reflow, the line layout which manages the bases updates its inline direction coordinate based on the preferred inline size for the corresponding text boxes. Next, the base is reflowed at the correct inline coordinate. Each paired text box is then also reflowed at the proper inline position determined by (1) the current position of its corresponding base and (2) its own preferred width. In computing intrinsic widths, accounting for spacing is less complicated. The minimum intrinsic width is the width of the widest ruby column, and the preferred intrinsic width is the sum of all the ruby column widths. Each ruby column width is the maximum width of its base box and text boxes. These individual widths are determined using GetPrefISize on the base and text boxes. Ruby base container frames store a list of pointers to the ruby text container frames in the segment they denote. This list of pointers is created in the ruby frame reflow method before calling the reflow method for the ruby base container. The list exists and is used only during reflow of the main ruby frame and is cleared before returning from reflow. --- layout/base/nsCSSFrameConstructor.cpp | 8 +- layout/base/nsLayoutUtils.cpp | 36 +++ layout/base/nsLayoutUtils.h | 8 + layout/generic/nsInlineFrame.cpp | 28 +-- layout/generic/nsLineLayout.cpp | 18 ++ layout/generic/nsLineLayout.h | 14 ++ layout/generic/nsRubyBaseContainerFrame.cpp | 163 ++++++++++++++ layout/generic/nsRubyBaseContainerFrame.h | 17 ++ layout/generic/nsRubyBaseFrame.cpp | 99 +++++++++ layout/generic/nsRubyBaseFrame.h | 14 ++ layout/generic/nsRubyFrame.cpp | 235 +++++++++++++++++++- layout/generic/nsRubyFrame.h | 13 ++ layout/generic/nsRubyTextContainerFrame.cpp | 130 +++++++++++ layout/generic/nsRubyTextContainerFrame.h | 23 ++ layout/generic/nsRubyTextFrame.cpp | 109 +++++++++ layout/generic/nsRubyTextFrame.h | 14 ++ layout/generic/nsTextFrame.cpp | 10 + 17 files changed, 908 insertions(+), 31 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index d85c39fc7e95..115feae12b57 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -4573,13 +4573,15 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay, FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewRubyFrame) }, { NS_STYLE_DISPLAY_RUBY_BASE, - FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer), + FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | + FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer), NS_NewRubyBaseFrame) }, { NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER, FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby), NS_NewRubyBaseContainerFrame) }, { NS_STYLE_DISPLAY_RUBY_TEXT, - FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer), + FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | + FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer), NS_NewRubyTextFrame) }, { NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER, FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby), @@ -9096,6 +9098,7 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = { }, { // Ruby Base FCDATA_DECL(FCDATA_USE_CHILD_ITEMS | + FCDATA_IS_LINE_PARTICIPANT | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer) | FCDATA_SKIP_FRAMESET, NS_NewRubyBaseFrame), @@ -9110,6 +9113,7 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = { }, { // Ruby Text FCDATA_DECL(FCDATA_USE_CHILD_ITEMS | + FCDATA_IS_LINE_PARTICIPANT | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer) | FCDATA_SKIP_FRAMESET, NS_NewRubyTextFrame), diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 2c28c242e063..197d8a17f55c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -6932,3 +6932,39 @@ nsLayoutUtils::IsOutlineStyleAutoEnabled() } return sOutlineStyleAutoEnabled; } + +/* static */ void +nsLayoutUtils::SetBSizeFromFontMetrics(const nsIFrame* aFrame, + nsHTMLReflowMetrics& aMetrics, + const nsHTMLReflowState& aReflowState, + LogicalMargin aFramePadding, + WritingMode aLineWM, + WritingMode aFrameWM) +{ + nsRefPtr fm; + float inflation = nsLayoutUtils::FontSizeInflationFor(aFrame); + nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm), inflation); + aReflowState.rendContext->SetFont(fm); + + if (fm) { + // Compute final height of the frame. + // + // Do things the standard css2 way -- though it's hard to find it + // in the css2 spec! It's actually found in the css1 spec section + // 4.4 (you will have to read between the lines to really see + // it). + // + // The height of our box is the sum of our font size plus the top + // and bottom border and padding. The height of children do not + // affect our height. + aMetrics.SetBlockStartAscent(fm->MaxAscent()); + aMetrics.BSize(aLineWM) = fm->MaxHeight(); + } else { + NS_WARNING("Cannot get font metrics - defaulting sizes to 0"); + aMetrics.SetBlockStartAscent(aMetrics.BSize(aLineWM) = 0); + } + aMetrics.SetBlockStartAscent(aMetrics.BlockStartAscent() + + aFramePadding.BStart(aFrameWM)); + aMetrics.BSize(aLineWM) += + aReflowState.ComputedLogicalBorderPadding().BStartEnd(aFrameWM); +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 83d55b93a131..c8b32cd1aed4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -27,6 +27,7 @@ #include "mozilla/gfx/2D.h" #include "Units.h" #include "mozilla/ToString.h" +#include "nsHTMLReflowMetrics.h" #include #include @@ -2269,6 +2270,13 @@ public: static bool IsOutlineStyleAutoEnabled(); + static void SetBSizeFromFontMetrics(const nsIFrame* aFrame, + nsHTMLReflowMetrics& aMetrics, + const nsHTMLReflowState& aReflowState, + mozilla::LogicalMargin aFramePadding, + mozilla::WritingMode aLineWM, + mozilla::WritingMode aFrameWM); + private: static uint32_t sFontSizeInflationEmPerLine; static uint32_t sFontSizeInflationMinTwips; diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 0f9ea4f83016..1052a216879b 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -705,32 +705,8 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, aMetrics.ISize(lineWM) += framePadding.IEnd(frameWM); } - nsRefPtr fm; - float inflation = nsLayoutUtils::FontSizeInflationFor(this); - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), inflation); - aReflowState.rendContext->SetFont(fm); - - if (fm) { - // Compute final height of the frame. - // - // Do things the standard css2 way -- though it's hard to find it - // in the css2 spec! It's actually found in the css1 spec section - // 4.4 (you will have to read between the lines to really see - // it). - // - // The height of our box is the sum of our font size plus the top - // and bottom border and padding. The height of children do not - // affect our height. - aMetrics.SetBlockStartAscent(fm->MaxAscent()); - aMetrics.BSize(lineWM) = fm->MaxHeight(); - } else { - NS_WARNING("Cannot get font metrics - defaulting sizes to 0"); - aMetrics.SetBlockStartAscent(aMetrics.BSize(lineWM) = 0); - } - aMetrics.SetBlockStartAscent(aMetrics.BlockStartAscent() + - framePadding.BStart(frameWM)); - aMetrics.BSize(lineWM) += - aReflowState.ComputedLogicalBorderPadding().BStartEnd(frameWM); + nsLayoutUtils::SetBSizeFromFontMetrics(this, aMetrics, aReflowState, + framePadding, lineWM, frameWM); // For now our overflow area is zero. The real value will be // computed in |nsLineLayout::RelativePositionFrames|. diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index d7059ba23fbd..5313aae2ea97 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -2734,3 +2734,21 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo } aOverflowAreas = overflowAreas; } + +void +nsLineLayout::AdvanceICoord(nscoord aAmount) +{ + mCurrentSpan->mICoord += aAmount; +} + +WritingMode +nsLineLayout::GetWritingMode() +{ + return mRootSpan->mWritingMode; +} + +nscoord +nsLineLayout::GetCurrentICoord() +{ + return mCurrentSpan->mICoord; +} diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 54d8b1680268..19f2fe122356 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -316,6 +316,20 @@ public: */ nscoord GetCurrentFrameInlineDistanceFromBlock(); + /** + * Move the inline position where the next frame will be reflowed forward by + * aAmount. + */ + void AdvanceICoord(nscoord aAmount); + /** + * Returns the writing mode for the root span. + */ + mozilla::WritingMode GetWritingMode(); + /** + * Returns the inline position where the next frame will be reflowed. + */ + nscoord GetCurrentICoord(); + protected: // This state is constant for a given block frame doing line layout nsFloatManager* mFloatManager; diff --git a/layout/generic/nsRubyBaseContainerFrame.cpp b/layout/generic/nsRubyBaseContainerFrame.cpp index acfaedcd334d..b04c1184d506 100644 --- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -7,8 +7,12 @@ /* rendering object for CSS "display: ruby-base-container" */ #include "nsRubyBaseContainerFrame.h" +#include "nsLineLayout.h" #include "nsPresContext.h" #include "nsStyleContext.h" +#include "WritingModes.h" + +using namespace mozilla; //---------------------------------------------------------------------- @@ -47,3 +51,162 @@ nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("RubyBaseContainer"), aResult); } #endif + + +void nsRubyBaseContainerFrame::AppendTextContainer(nsIFrame* aFrame) +{ + nsRubyTextContainerFrame* rtcFrame = do_QueryFrame(aFrame); + if (rtcFrame) { + mTextContainers.AppendElement(rtcFrame); + } +} + +void nsRubyBaseContainerFrame::ClearTextContainers() { + mTextContainers.Clear(); +} + +/* virtual */ void +nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsRubyBaseContainerFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + + if (!aReflowState.mLineLayout) { + NS_ASSERTION( + aReflowState.mLineLayout, + "No line layout provided to RubyBaseContainerFrame reflow method."); + aStatus = NS_FRAME_COMPLETE; + return; + } + + aStatus = NS_FRAME_COMPLETE; + nscoord isize = 0; + int baseNum = 0; + nscoord leftoverSpace = 0; + nscoord spaceApart = 0; + WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + WritingMode frameWM = aReflowState.GetWritingMode(); + LogicalMargin borderPadding = + aReflowState.ComputedLogicalBorderPadding(); + nscoord baseStart = 0; + + LogicalSize availSize(lineWM, aReflowState.AvailableWidth(), + aReflowState.AvailableHeight()); + + // Begin the line layout for each ruby text container in advance. + for (uint32_t i = 0; i < mTextContainers.Length(); i++) { + nsRubyTextContainerFrame* rtcFrame = mTextContainers.ElementAt(i); + nsHTMLReflowState rtcReflowState(aPresContext, + *aReflowState.parentReflowState, + rtcFrame, availSize); + rtcReflowState.mLineLayout = aReflowState.mLineLayout; + // FIXME: Avoid using/needing the rtcReflowState argument + rtcFrame->BeginRTCLineLayout(aPresContext, rtcReflowState); + } + + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nsIFrame* rbFrame = e.get(); + if (rbFrame->GetType() != nsGkAtoms::rubyBaseFrame) { + NS_ASSERTION(false, "Unrecognized child type for ruby base container"); + continue; + } + + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + + // Determine if we need more spacing between bases in the inline direction + // depending on the inline size of the corresponding annotations + // FIXME: The use of GetPrefISize here and below is easier but not ideal. It + // would be better to use metrics from reflow. + nscoord prefWidth = rbFrame->GetPrefISize(aReflowState.rendContext); + nscoord textWidth = 0; + + for (uint32_t i = 0; i < mTextContainers.Length(); i++) { + nsRubyTextFrame* rtFrame = do_QueryFrame(mTextContainers.ElementAt(i)-> + PrincipalChildList().FrameAt(baseNum)); + if (rtFrame) { + int newWidth = rtFrame->GetPrefISize(aReflowState.rendContext); + if (newWidth > textWidth) { + textWidth = newWidth; + } + } + } + if (textWidth > prefWidth) { + spaceApart = std::max((textWidth - prefWidth) / 2, spaceApart); + leftoverSpace = spaceApart; + } else { + spaceApart = leftoverSpace; + leftoverSpace = 0; + } + if (spaceApart > 0) { + aReflowState.mLineLayout->AdvanceICoord(spaceApart); + } + baseStart = aReflowState.mLineLayout->GetCurrentICoord(); + + bool pushedFrame; + aReflowState.mLineLayout->ReflowFrame(rbFrame, frameReflowStatus, + &metrics, pushedFrame); + NS_ASSERTION(!pushedFrame, "Ruby line breaking is not yet implemented"); + + isize += metrics.ISize(lineWM); + rbFrame->SetSize(LogicalSize(lineWM, metrics.ISize(lineWM), + metrics.BSize(lineWM))); + FinishReflowChild(rbFrame, aPresContext, metrics, &aReflowState, 0, 0, + NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_MOVE_VIEW); + + // Now reflow the ruby text boxes that correspond to this ruby base box. + for (uint32_t i = 0; i < mTextContainers.Length(); i++) { + nsRubyTextFrame* rtFrame = do_QueryFrame(mTextContainers.ElementAt(i)-> + PrincipalChildList().FrameAt(baseNum)); + nsRubyTextContainerFrame* rtcFrame = mTextContainers.ElementAt(i); + if (rtFrame) { + nsHTMLReflowMetrics rtcMetrics(*aReflowState.parentReflowState, + aDesiredSize.mFlags); + nsHTMLReflowState rtcReflowState(aPresContext, + *aReflowState.parentReflowState, + rtcFrame, availSize); + rtcReflowState.mLineLayout = rtcFrame->GetLineLayout(); + rtcFrame->ReflowRubyTextFrame(rtFrame, rbFrame, baseStart, + aPresContext, rtcMetrics, + rtcReflowState); + } + } + baseNum++; + } + + // Reflow ruby annotations which do not have a corresponding ruby base box due + // to a ruby base shortage. According to the spec, an empty ruby base is + // assumed to exist for each of these annotations. + bool continueReflow = true; + while (continueReflow) { + continueReflow = false; + for (uint32_t i = 0; i < mTextContainers.Length(); i++) { + nsRubyTextFrame* rtFrame = do_QueryFrame(mTextContainers.ElementAt(i)-> + PrincipalChildList().FrameAt(baseNum)); + nsRubyTextContainerFrame* rtcFrame = mTextContainers.ElementAt(i); + if (rtFrame) { + continueReflow = true; + nsHTMLReflowMetrics rtcMetrics(*aReflowState.parentReflowState, + aDesiredSize.mFlags); + nsHTMLReflowState rtcReflowState(aPresContext, + *aReflowState.parentReflowState, + rtcFrame, availSize); + rtcReflowState.mLineLayout = rtcFrame->GetLineLayout(); + rtcFrame->ReflowRubyTextFrame(rtFrame, nullptr, baseStart, + aPresContext, rtcMetrics, + rtcReflowState); + // Update the inline coord to make space for subsequent ruby annotations + // (since there is no corresponding base inline size to use). + baseStart += rtcMetrics.ISize(lineWM); + } + } + baseNum++; + } + + aDesiredSize.ISize(lineWM) = isize; + nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, aReflowState, + borderPadding, lineWM, frameWM); +} diff --git a/layout/generic/nsRubyBaseContainerFrame.h b/layout/generic/nsRubyBaseContainerFrame.h index 60c4b5e5302f..85a161b99c80 100644 --- a/layout/generic/nsRubyBaseContainerFrame.h +++ b/layout/generic/nsRubyBaseContainerFrame.h @@ -10,6 +10,9 @@ #define nsRubyBaseContainerFrame_h___ #include "nsContainerFrame.h" +#include "nsRubyTextContainerFrame.h" +#include "nsRubyBaseFrame.h" +#include "nsRubyTextFrame.h" /** * Factory function. @@ -27,16 +30,30 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual void Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif + void AppendTextContainer(nsIFrame* aFrame); + void ClearTextContainers(); + protected: friend nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} + /* + * The ruby text containers that belong to the ruby segment defined by + * this ruby base container. These text containers are located at the start + * of reflow for the ruby frame (parent) and cleared at the end of that + * reflow. + */ + nsTArray mTextContainers; }; #endif /* nsRubyBaseContainerFrame_h___ */ diff --git a/layout/generic/nsRubyBaseFrame.cpp b/layout/generic/nsRubyBaseFrame.cpp index c8f0d60da0a9..447a7c349bd0 100644 --- a/layout/generic/nsRubyBaseFrame.cpp +++ b/layout/generic/nsRubyBaseFrame.cpp @@ -7,8 +7,12 @@ /* rendering object for CSS "display: ruby-base" */ #include "nsRubyBaseFrame.h" +#include "nsLineLayout.h" #include "nsPresContext.h" #include "nsStyleContext.h" +#include "WritingModes.h" + +using namespace mozilla; //---------------------------------------------------------------------- @@ -47,3 +51,98 @@ nsRubyBaseFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("RubyBase"), aResult); } #endif + +nscoord +nsRubyBaseFrame::GetMinISize(nsRenderingContext *aRenderingContext) +{ + return nsLayoutUtils::MinISizeFromInline(this, aRenderingContext); +} + +nscoord +nsRubyBaseFrame::GetPrefISize(nsRenderingContext *aRenderingContext) +{ + return nsLayoutUtils::PrefISizeFromInline(this, aRenderingContext); +} + +/* virtual */ void +nsRubyBaseFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlineMinISizeData *aData) +{ + for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { + e.get()->AddInlineMinISize(aRenderingContext, aData); + } +} + +/* virtual */ void +nsRubyBaseFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlinePrefISizeData *aData) +{ + for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { + e.get()->AddInlinePrefISize(aRenderingContext, aData); + } +} + +/* virtual */ bool +nsRubyBaseFrame::IsFrameOfType(uint32_t aFlags) const +{ + return nsContainerFrame::IsFrameOfType(aFlags & + ~(nsIFrame::eLineParticipant)); +} + +/* virtual */ nscoord +nsRubyBaseFrame::GetLogicalBaseline(WritingMode aWritingMode) const +{ + return mBaseline; +} + +/* virtual */ void +nsRubyBaseFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsRubyBaseFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + + if (!aReflowState.mLineLayout) { + NS_ASSERTION(aReflowState.mLineLayout, + "No line layout provided to RubyBaseFrame reflow method."); + aStatus = NS_FRAME_COMPLETE; + return; + } + + WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + WritingMode frameWM = aReflowState.GetWritingMode(); + aStatus = NS_FRAME_COMPLETE; + LogicalSize availSize(lineWM, aReflowState.AvailableWidth(), + aReflowState.AvailableHeight()); + LogicalMargin borderPadding = aReflowState.ComputedLogicalBorderPadding(); + + // Begin the span for the ruby base frame + nscoord availableISize = aReflowState.AvailableISize(); + NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE, + "should no longer use available widths"); + // Subtract off inline axis border+padding from availableISize + availableISize -= borderPadding.IStartEnd(frameWM); + aReflowState.mLineLayout->BeginSpan(this, &aReflowState, + borderPadding.IStart(frameWM), + availableISize, &mBaseline); + + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + + bool pushedFrame; + aReflowState.mLineLayout->ReflowFrame(e.get(), frameReflowStatus, + &metrics, pushedFrame); + NS_ASSERTION(!pushedFrame, + "Ruby line breaking is not yet implemented"); + + e.get()->SetSize(LogicalSize(lineWM, metrics.ISize(lineWM), + metrics.BSize(lineWM))); + } + + aDesiredSize.ISize(lineWM) = aReflowState.mLineLayout->EndSpan(this); + nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, aReflowState, + borderPadding, lineWM, frameWM); +} diff --git a/layout/generic/nsRubyBaseFrame.h b/layout/generic/nsRubyBaseFrame.h index 973d21621583..33012cf20eb4 100644 --- a/layout/generic/nsRubyBaseFrame.h +++ b/layout/generic/nsRubyBaseFrame.h @@ -27,6 +27,19 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext, + InlineMinISizeData *aData) MOZ_OVERRIDE; + virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext, + InlinePrefISizeData *aData) MOZ_OVERRIDE; + virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; + virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext); + virtual void Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; + virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) + const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; @@ -36,6 +49,7 @@ protected: friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsRubyBaseFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} + nscoord mBaseline; }; #endif /* nsRubyBaseFrame_h___ */ diff --git a/layout/generic/nsRubyFrame.cpp b/layout/generic/nsRubyFrame.cpp index 2787b27b6eec..641a762b878c 100644 --- a/layout/generic/nsRubyFrame.cpp +++ b/layout/generic/nsRubyFrame.cpp @@ -6,8 +6,14 @@ /* rendering object for CSS "display: ruby" */ #include "nsRubyFrame.h" +#include "nsLineLayout.h" #include "nsPresContext.h" #include "nsStyleContext.h" +#include "WritingModes.h" +#include "nsRubyBaseContainerFrame.h" +#include "nsRubyTextContainerFrame.h" + +using namespace mozilla; //---------------------------------------------------------------------- @@ -27,7 +33,6 @@ NS_NewRubyFrame(nsIPresShell* aPresShell, return new (aPresShell) nsRubyFrame(aContext); } - //---------------------------------------------------------------------- // nsRubyFrame Method Implementations @@ -39,11 +44,11 @@ nsRubyFrame::GetType() const return nsGkAtoms::rubyFrame; } -bool +/* virtual */ bool nsRubyFrame::IsFrameOfType(uint32_t aFlags) const { return nsContainerFrame::IsFrameOfType(aFlags & - ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant)); + ~(nsIFrame::eLineParticipant)); } #ifdef DEBUG_FRAME_DUMP @@ -53,3 +58,227 @@ nsRubyFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("Ruby"), aResult); } #endif + +void +nsRubyFrame::CalculateColSizes(nsRenderingContext* aRenderingContext, + nsTArray& aColSizes) +{ + nsFrameList::Enumerator e(this->PrincipalChildList()); + uint32_t annotationNum = 0; + int segmentNum = -1; + + nsTArray segmentBaseCounts; + + for(; !e.AtEnd(); e.Next()) { + nsIFrame* childFrame = e.get(); + if (childFrame->GetType() == nsGkAtoms::rubyBaseContainerFrame) { + segmentNum++; + segmentBaseCounts.AppendElement(0); + nsFrameList::Enumerator bases(childFrame->PrincipalChildList()); + for(; !bases.AtEnd(); bases.Next()) { + aColSizes.AppendElement(bases.get()->GetPrefISize(aRenderingContext)); + segmentBaseCounts.ElementAt(segmentNum)++; + } + } else if (childFrame->GetType() == nsGkAtoms::rubyTextContainerFrame) { + if (segmentNum == -1) { + // No rbc exists for first segment, so act as if there is one + segmentNum++; + segmentBaseCounts.AppendElement(1); + aColSizes.AppendElement(0); + } + nsFrameList::Enumerator annotations(childFrame->PrincipalChildList()); + uint32_t baseCount = segmentBaseCounts.ElementAt(segmentNum); + for(; !annotations.AtEnd(); annotations.Next()) { + nsIFrame* annotationFrame = annotations.get(); + if (annotationNum > baseCount) { + aColSizes.AppendElement(annotationFrame-> + GetPrefISize(aRenderingContext)); + baseCount++; + segmentBaseCounts.ElementAt(segmentNum) = baseCount; + annotationNum++; + } else if (annotationNum < baseCount - 1) { + //there are fewer annotations than bases, so the last annotation is + //associated with (spans) the remaining bases. This means these + //columns can't be broken up, so gather their entire ISize in one + //entry of aColSizes and clear the other entries. + int baseSum = 0; + for (uint32_t i = annotationNum; i < annotationNum + baseCount; i++) { + baseSum += aColSizes.ElementAt(i); + if (i > annotationNum) { + aColSizes.ElementAt(i) = 0; + } + } + aColSizes.ElementAt(annotationNum) = + std::max(baseSum, annotationFrame->GetPrefISize(aRenderingContext)); + annotationNum = baseCount; + } else { + aColSizes.ElementAt(annotationNum) = + std::max(aColSizes.ElementAt(annotationNum), + annotationFrame->GetPrefISize(aRenderingContext)); + annotationNum++; + } + } + } else { + NS_ASSERTION(false, "Unrecognized child type for ruby frame."); + } + } +} + +/* virtual */ void +nsRubyFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlineMinISizeData *aData) +{ + //FIXME: This needs to handle the cases where it's possible for a ruby base to + //break, as well as forced breaks. + nsTArray colSizes; + CalculateColSizes(aRenderingContext, colSizes); + + nscoord max = 0; + for (uint32_t i = 0; i < colSizes.Length(); i++) { + if (colSizes.ElementAt(i) > max) { + max = colSizes.ElementAt(i); + } + } + + aData->currentLine += max; +} + +/* virtual */ void +nsRubyFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlinePrefISizeData *aData) +{ + nsTArray colSizes; + CalculateColSizes(aRenderingContext, colSizes); + + nscoord sum = 0; + for (uint32_t i = 0; i < colSizes.Length(); i++) { + sum += colSizes.ElementAt(i); + } + + aData->currentLine += sum; +} + +/* virtual */ nscoord +nsRubyFrame::GetLogicalBaseline(WritingMode aWritingMode) const +{ + return mBaseline; +} + +/* virtual */ void +nsRubyFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsRubyFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + + if (!aReflowState.mLineLayout) { + NS_ASSERTION(aReflowState.mLineLayout, + "No line layout provided to RubyFrame reflow method."); + aStatus = NS_FRAME_COMPLETE; + return; + } + + // Begin the span for the ruby frame + WritingMode frameWM = aReflowState.GetWritingMode(); + WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + LogicalMargin borderPadding = aReflowState.ComputedLogicalBorderPadding(); + nscoord availableISize = aReflowState.AvailableISize(); + NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE, + "should no longer use available widths"); + // Subtract off inline axis border+padding from availableISize + availableISize -= borderPadding.IStartEnd(frameWM); + aReflowState.mLineLayout->BeginSpan(this, &aReflowState, + borderPadding.IStart(frameWM), + availableISize, &mBaseline); + + // FIXME: line breaking / continuations not yet implemented + aStatus = NS_FRAME_COMPLETE; + LogicalSize availSize(lineWM, aReflowState.AvailableISize(), + aReflowState.AvailableBSize()); + // The ruby base container for the current segment + nsRubyBaseContainerFrame* segmentRBC = nullptr; + nscoord annotationBSize = 0; + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nsIFrame* childFrame = e.get(); + if (e.get()->GetType() == nsGkAtoms::rubyBaseContainerFrame) { + if (segmentRBC) { + annotationBSize = 0; + } + + // Figure out what all the text containers are for this segment (necessary + // for reflow calculations) + segmentRBC = do_QueryFrame(childFrame); + nsFrameList::Enumerator segment(e); + segment.Next(); + while (!segment.AtEnd() && (segment.get()->GetType() != + nsGkAtoms::rubyBaseContainerFrame)) { + if (segment.get()->GetType() == nsGkAtoms::rubyTextContainerFrame) { + segmentRBC->AppendTextContainer(segment.get()); + } + segment.Next(); + } + + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + nsHTMLReflowState childReflowState(aPresContext, aReflowState, + childFrame, availSize); + childReflowState.mLineLayout = aReflowState.mLineLayout; + childFrame->Reflow(aPresContext, metrics, childReflowState, + frameReflowStatus); + NS_ASSERTION(frameReflowStatus == NS_FRAME_COMPLETE, + "Ruby line breaking is not yet implemented"); + childFrame->SetSize(LogicalSize(lineWM, metrics.ISize(lineWM), + metrics.BSize(lineWM))); + FinishReflowChild(childFrame, aPresContext, metrics, &childReflowState, 0, + 0, NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_MOVE_VIEW); + + } else if (childFrame->GetType() == nsGkAtoms::rubyTextContainerFrame) { + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, + availSize); + childReflowState.mLineLayout = aReflowState.mLineLayout; + childFrame->Reflow(aPresContext, metrics, childReflowState, + frameReflowStatus); + NS_ASSERTION(frameReflowStatus == NS_FRAME_COMPLETE, + "Ruby line breaking is not yet implemented"); + annotationBSize += metrics.BSize(lineWM); + childFrame->SetSize(LogicalSize(lineWM, metrics.ISize(lineWM), + metrics.BSize(lineWM))); + // FIXME: This is a temporary calculation for finding the block coordinate + // of the ruby text container. A better one replace it once it's been + // spec'ed. + nscoord baseContainerBCoord; + if (segmentRBC) { + // Find the starting block coordinate of the ruby base container for + // this segment. For now, the ruby text container will be placed so that + // its bottom edge touches this coordinate. + baseContainerBCoord = segmentRBC-> + GetLogicalPosition(this->GetParent()->GetLogicalSize().ISize(lineWM)). + B(lineWM); + } else { + baseContainerBCoord = 0; + } + FinishReflowChild(childFrame, aPresContext, metrics, &childReflowState, 0, + baseContainerBCoord - metrics.BSize(lineWM), 0); + } else { + NS_NOTREACHED( + "Unrecognized child type for ruby frame will not be reflowed."); + } + } + + // Null the pointers between child frames. + for (nsFrameList::Enumerator children(mFrames); !children.AtEnd(); + children.Next()) { + nsRubyBaseContainerFrame* rbcFrame = do_QueryFrame(children.get()); + if (rbcFrame) { + rbcFrame->ClearTextContainers(); + } + } + + aDesiredSize.ISize(lineWM) = aReflowState.mLineLayout->EndSpan(this); + nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, aReflowState, + borderPadding, lineWM, frameWM); +} diff --git a/layout/generic/nsRubyFrame.h b/layout/generic/nsRubyFrame.h index 6c41b3a1269b..b9c9096d6bf1 100644 --- a/layout/generic/nsRubyFrame.h +++ b/layout/generic/nsRubyFrame.h @@ -28,6 +28,16 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; + virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext, + InlineMinISizeData *aData) MOZ_OVERRIDE; + virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext, + InlinePrefISizeData *aData) MOZ_OVERRIDE; + virtual void Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; + virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) + const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; @@ -37,6 +47,9 @@ protected: friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsRubyFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} + void CalculateColSizes(nsRenderingContext* aRenderingContext, + nsTArray& aColSizes); + nscoord mBaseline; }; #endif /* nsRubyFrame_h___ */ diff --git a/layout/generic/nsRubyTextContainerFrame.cpp b/layout/generic/nsRubyTextContainerFrame.cpp index 2b2db9740a73..52dd45300850 100644 --- a/layout/generic/nsRubyTextContainerFrame.cpp +++ b/layout/generic/nsRubyTextContainerFrame.cpp @@ -9,6 +9,8 @@ #include "nsRubyTextContainerFrame.h" #include "nsPresContext.h" #include "nsStyleContext.h" +#include "WritingModes.h" +#include "mozilla/UniquePtr.h" //---------------------------------------------------------------------- @@ -47,3 +49,131 @@ nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("RubyTextContainer"), aResult); } #endif + +void +nsRubyTextContainerFrame::BeginRTCLineLayout(nsPresContext* aPresContext, + const nsHTMLReflowState& aReflowState) +{ + // Construct block reflow state and line layout + nscoord consumedBSize = GetConsumedBSize(); + + ClearLineCursor(); + + mISize = 0; + + nsBlockReflowState state(aReflowState, aPresContext, this, true, true, + false, consumedBSize); + + NS_ASSERTION(!mLines.empty(), + "There should be at least one line in the ruby text container"); + line_iterator firstLine = begin_lines(); + mLineLayout = mozilla::MakeUnique( + state.mPresContext, + state.mReflowState.mFloatManager, + &state.mReflowState, &firstLine); + mLineLayout->Init(&state, state.mMinLineHeight, state.mLineNumber); + + mozilla::WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + mozilla::LogicalRect lineRect(state.mContentArea); + nscoord iStart = lineRect.IStart(lineWM); + nscoord availISize = lineRect.ISize(lineWM); + nscoord availBSize = NS_UNCONSTRAINEDSIZE; + + mLineLayout->BeginLineReflow(iStart, state.mBCoord, + availISize, availBSize, + false, + false, + lineWM, state.mContainerWidth); +} + +void +nsRubyTextContainerFrame::ReflowRubyTextFrame( + nsRubyTextFrame* rtFrame, + nsIFrame* rbFrame, + nscoord baseStart, + nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState) +{ + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + mozilla::WritingMode lineWM = mLineLayout->GetWritingMode(); + mozilla::LogicalSize availSize(lineWM, aReflowState.AvailableWidth(), + aReflowState.AvailableHeight()); + nsHTMLReflowState childReflowState(aPresContext, aReflowState, rtFrame, availSize); + + // Determine the inline coordinate for the text frame by centering over + // the corresponding base frame + int baseWidth; + if (rbFrame) { + baseWidth = rbFrame->ISize(); + + // If this is the last ruby annotation, it gets paired with ALL remaining + // ruby bases + if (!rtFrame->GetNextSibling()) { + rbFrame = rbFrame->GetNextSibling(); + while (rbFrame) { + baseWidth += rbFrame->ISize(); + rbFrame = rbFrame->GetNextSibling(); + } + } + } else { + baseWidth = 0; + } + + int baseCenter = baseStart + baseWidth / 2; + // FIXME: Find a way to avoid using GetPrefISize here, potentially by moving + // the frame after it has reflowed. + nscoord ICoord = baseCenter - rtFrame->GetPrefISize(aReflowState.rendContext) / 2; + if (ICoord > mLineLayout->GetCurrentICoord()) { + mLineLayout->AdvanceICoord(ICoord - mLineLayout->GetCurrentICoord()); + } + + bool pushedFrame; + mLineLayout->ReflowFrame(rtFrame, frameReflowStatus, + &metrics, pushedFrame); + + NS_ASSERTION(!pushedFrame, "Ruby line breaking is not yet implemented"); + + mISize += metrics.ISize(lineWM); + rtFrame->SetSize(nsSize(metrics.ISize(lineWM), metrics.BSize(lineWM))); + FinishReflowChild(rtFrame, aPresContext, metrics, &childReflowState, 0, 0, + NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_MOVE_VIEW); +} + +/* virtual */ void +nsRubyTextContainerFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsRubyTextContainerFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + + // All rt children have already been reflowed. All we need to do is clean up + // the line layout. + + aStatus = NS_FRAME_COMPLETE; + mozilla::WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + mozilla::WritingMode frameWM = aReflowState.GetWritingMode(); + mozilla::LogicalMargin borderPadding = + aReflowState.ComputedLogicalBorderPadding(); + + aDesiredSize.ISize(lineWM) = mISize; + nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, aReflowState, + borderPadding, lineWM, frameWM); + + nscoord bsize = aDesiredSize.BSize(lineWM); + if (!mLines.empty()) { + // Okay to use BlockStartAscent because it has just been correctly set by + // nsLayoutUtils::SetBSizeFromFontMetrics. + mLines.begin()->SetLogicalAscent(aDesiredSize.BlockStartAscent()); + mLines.begin()->SetBounds(aReflowState.GetWritingMode(), 0, 0, mISize, + bsize, mISize); + } + + if (mLineLayout) { + mLineLayout->EndLineReflow(); + mLineLayout = nullptr; + } +} diff --git a/layout/generic/nsRubyTextContainerFrame.h b/layout/generic/nsRubyTextContainerFrame.h index 4d71030ebedb..83def7095808 100644 --- a/layout/generic/nsRubyTextContainerFrame.h +++ b/layout/generic/nsRubyTextContainerFrame.h @@ -10,6 +10,9 @@ #define nsRubyTextContainerFrame_h___ #include "nsBlockFrame.h" +#include "nsRubyBaseFrame.h" +#include "nsRubyTextFrame.h" +#include "nsLineLayout.h" /** * Factory function. @@ -30,16 +33,36 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual void Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif + void ReflowRubyTextFrame(nsRubyTextFrame* rtFrame, nsIFrame* rbFrame, + nscoord baseStart, nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState); + void BeginRTCLineLayout(nsPresContext* aPresContext, + const nsHTMLReflowState& aReflowState); + nsLineLayout* GetLineLayout() { return mLineLayout.get(); }; + protected: friend nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsRubyTextContainerFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) {} + // This pointer is active only during reflow of the ruby structure. It gets + // created when the corresponding ruby base container is reflowed, and it is + // destroyed when the ruby text container itself is reflowed. + mozilla::UniquePtr mLineLayout; + // The intended dimensions of the ruby text container. These are modified + // whenever a ruby text box is reflowed and used when the ruby text container + // is reflowed. + nscoord mISize; }; #endif /* nsRubyTextContainerFrame_h___ */ diff --git a/layout/generic/nsRubyTextFrame.cpp b/layout/generic/nsRubyTextFrame.cpp index bc833c3ad790..06c5da11e917 100644 --- a/layout/generic/nsRubyTextFrame.cpp +++ b/layout/generic/nsRubyTextFrame.cpp @@ -9,6 +9,10 @@ #include "nsRubyTextFrame.h" #include "nsPresContext.h" #include "nsStyleContext.h" +#include "WritingModes.h" +#include "nsLineLayout.h" + +using namespace mozilla; //---------------------------------------------------------------------- @@ -47,3 +51,108 @@ nsRubyTextFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("RubyText"), aResult); } #endif + +/* virtual */ bool +nsRubyTextFrame::IsFrameOfType(uint32_t aFlags) const +{ + return nsContainerFrame::IsFrameOfType(aFlags & + ~(nsIFrame::eLineParticipant)); +} + +/* virtual */ nscoord +nsRubyTextFrame::GetMinISize(nsRenderingContext *aRenderingContext) +{ + return nsLayoutUtils::MinISizeFromInline(this, aRenderingContext); +} + +/* virtual */ nscoord +nsRubyTextFrame::GetPrefISize(nsRenderingContext *aRenderingContext) +{ + return nsLayoutUtils::PrefISizeFromInline(this, aRenderingContext); +} + +/* virtual */ void +nsRubyTextFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlineMinISizeData *aData) +{ + // FIXME: See the fixme in AddInlinePrefISize. + aData->lineContainer = this; + + for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { + e.get()->AddInlineMinISize(aRenderingContext, aData); + } +} + +/* virtual */ void +nsRubyTextFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext, + nsIFrame::InlinePrefISizeData *aData) +{ + // FIXME: We shouldn't need to set this, but it prevents us from tripping an + // assertion in nsTextFrame.cpp because FindLineContainer on a child frame will + // return the ruby text box (us) instead of the ruby text container (our + // parent). A fix would need to be made to FindLineContainer and/or + // CanContinueTextRun so that this line can be removed. + aData->lineContainer = this; + + for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { + e.get()->AddInlinePrefISize(aRenderingContext, aData); + } +} + +/* virtual */ nscoord +nsRubyTextFrame::GetLogicalBaseline(WritingMode aWritingMode) const +{ + return mBaseline; +} + +/* virtual */ void +nsRubyTextFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsRubyBaseFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + + if (!aReflowState.mLineLayout) { + NS_ASSERTION(aReflowState.mLineLayout, + "No line layout provided to RubyTextFrame reflow method."); + aStatus = NS_FRAME_COMPLETE; + return; + } + + WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); + WritingMode frameWM = aReflowState.GetWritingMode(); + LogicalMargin borderPadding = aReflowState.ComputedLogicalBorderPadding(); + aStatus = NS_FRAME_COMPLETE; + LogicalSize availSize(lineWM, aReflowState.AvailableWidth(), + aReflowState.AvailableHeight()); + + // Begin the span for the ruby text frame + nscoord availableISize = aReflowState.AvailableISize(); + NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE, + "should no longer use available widths"); + // Subtract off inline axis border+padding from availableISize + availableISize -= borderPadding.IStartEnd(frameWM); + aReflowState.mLineLayout->BeginSpan(this, &aReflowState, + borderPadding.IStart(frameWM), + availableISize, &mBaseline); + + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nsReflowStatus frameReflowStatus; + nsHTMLReflowMetrics metrics(aReflowState, aDesiredSize.mFlags); + + bool pushedFrame; + aReflowState.mLineLayout->ReflowFrame(e.get(), frameReflowStatus, + &metrics, pushedFrame); + NS_ASSERTION(!pushedFrame, + "Ruby line breaking is not yet implemented"); + e.get()->SetSize(LogicalSize(lineWM, metrics.ISize(lineWM), + metrics.BSize(lineWM))); + } + + aDesiredSize.ISize(lineWM) = aReflowState.mLineLayout->EndSpan(this); + nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize, aReflowState, + borderPadding, lineWM, frameWM); + +} diff --git a/layout/generic/nsRubyTextFrame.h b/layout/generic/nsRubyTextFrame.h index a6fe02f12d0b..e680eafa182d 100644 --- a/layout/generic/nsRubyTextFrame.h +++ b/layout/generic/nsRubyTextFrame.h @@ -27,6 +27,19 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual void Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; + virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext, + InlineMinISizeData *aData) MOZ_OVERRIDE; + virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext, + InlinePrefISizeData *aData) MOZ_OVERRIDE; + virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; + virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; + virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) + const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; @@ -36,6 +49,7 @@ protected: friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); nsRubyTextFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} + nscoord mBaseline; }; #endif /* nsRubyTextFrame_h___ */ diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index e724147de71c..9a17b1194090 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1131,6 +1131,15 @@ CanTextCrossFrameBoundary(nsIFrame* aFrame, nsIAtom* aType) result.mScanSiblings = true; result.mTextRunCanCrossFrameBoundary = true; result.mLineBreakerCanCrossFrameBoundary = true; + } else if (aFrame->GetType() == nsGkAtoms::rubyTextFrame) { + result.mFrameToScan = aFrame->GetFirstPrincipalChild(); + result.mOverflowFrameToScan = + aFrame->GetFirstChild(nsIFrame::kOverflowList); + NS_WARN_IF_FALSE(!result.mOverflowFrameToScan, + "Scanning overflow inline frames is something we should avoid"); + result.mScanSiblings = true; + result.mTextRunCanCrossFrameBoundary = false; + result.mLineBreakerCanCrossFrameBoundary = false; } else { result.mFrameToScan = nullptr; result.mOverflowFrameToScan = nullptr; @@ -1244,6 +1253,7 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, } else { NS_ASSERTION(!aForFrame || (aLineContainer == FindLineContainer(aForFrame) || + aLineContainer->GetType() == nsGkAtoms::rubyTextContainerFrame || (aLineContainer->GetType() == nsGkAtoms::letterFrame && aLineContainer->IsFloating())), "Wrong line container hint"); From aca0a15a6add8645daab6bed9c3d248057a4b8b2 Mon Sep 17 00:00:00 2001 From: Susanna Bowen Date: Fri, 15 Aug 2014 10:34:20 -0700 Subject: [PATCH 46/86] Bug 1039017 - Reftests for ruby whitespace handling. r=dholbert --- layout/reftests/css-ruby/reftest.list | 4 +++ .../css-ruby/ruby-whitespace-1-ref.html | 35 +++++++++++++++++++ .../reftests/css-ruby/ruby-whitespace-1.html | 28 +++++++++++++++ .../css-ruby/ruby-whitespace-2-ref.html | 28 +++++++++++++++ .../reftests/css-ruby/ruby-whitespace-2.html | 27 ++++++++++++++ layout/reftests/reftest.list | 3 ++ 6 files changed, 125 insertions(+) create mode 100644 layout/reftests/css-ruby/reftest.list create mode 100644 layout/reftests/css-ruby/ruby-whitespace-1-ref.html create mode 100644 layout/reftests/css-ruby/ruby-whitespace-1.html create mode 100644 layout/reftests/css-ruby/ruby-whitespace-2-ref.html create mode 100644 layout/reftests/css-ruby/ruby-whitespace-2.html diff --git a/layout/reftests/css-ruby/reftest.list b/layout/reftests/css-ruby/reftest.list new file mode 100644 index 000000000000..9a52cbf2599f --- /dev/null +++ b/layout/reftests/css-ruby/reftest.list @@ -0,0 +1,4 @@ +default-preferences pref(layout.css.ruby.enabled,true) + +asserts(1) == ruby-whitespace-1.html ruby-whitespace-1-ref.html # bug 1052145 +== ruby-whitespace-2.html ruby-whitespace-2-ref.html diff --git a/layout/reftests/css-ruby/ruby-whitespace-1-ref.html b/layout/reftests/css-ruby/ruby-whitespace-1-ref.html new file mode 100644 index 000000000000..5b5a50920bea --- /dev/null +++ b/layout/reftests/css-ruby/ruby-whitespace-1-ref.html @@ -0,0 +1,35 @@ + + + + + + + + + Base threeText two Segment two + + Base two Text two + + Base two + + + diff --git a/layout/reftests/css-ruby/ruby-whitespace-1.html b/layout/reftests/css-ruby/ruby-whitespace-1.html new file mode 100644 index 000000000000..7710df648297 --- /dev/null +++ b/layout/reftests/css-ruby/ruby-whitespace-1.html @@ -0,0 +1,28 @@ + + + + + + + + + Base three + Text two + Segment two + + + Base two Text two + + Base two + + + diff --git a/layout/reftests/css-ruby/ruby-whitespace-2-ref.html b/layout/reftests/css-ruby/ruby-whitespace-2-ref.html new file mode 100644 index 000000000000..518f85d44988 --- /dev/null +++ b/layout/reftests/css-ruby/ruby-whitespace-2-ref.html @@ -0,0 +1,28 @@ + + + + + + + + + + +abcd BASETEXT + +abcdBASETEXT + +abcd BASETEXT + + + + + diff --git a/layout/reftests/css-ruby/ruby-whitespace-2.html b/layout/reftests/css-ruby/ruby-whitespace-2.html new file mode 100644 index 000000000000..71d5904c4505 --- /dev/null +++ b/layout/reftests/css-ruby/ruby-whitespace-2.html @@ -0,0 +1,27 @@ + + + + + + + + + +abcd BASETEXT + +abcd BASETEXT + +abcd BASETEXT + + + + + diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list index d196ec7b2f42..c7feb07f09b7 100644 --- a/layout/reftests/reftest.list +++ b/layout/reftests/reftest.list @@ -90,6 +90,9 @@ include css-parsing/reftest.list # css placeholder include css-placeholder/reftest.list +# css ruby +include css-ruby/reftest.list + # css required include css-required/reftest.list From c622b18e0557fe951d33de1463a5104f09b000ed Mon Sep 17 00:00:00 2001 From: Susanna Bowen Date: Fri, 15 Aug 2014 10:34:20 -0700 Subject: [PATCH 47/86] Bug 1030993 - Fix assertion failure in reftest css-ruby/ruby-whitespace-1.html. r=dbaron Fixes the assertion failure with text: "###!!! ASSERTION: Wrong line container hint: '!aForFrame || (aLineContainer == FindLineContainer(aForFrame) || aLineContainer->GetType() == nsGkAtoms::rubyTextContainerFrame || (aLineContainer->GetType() == nsGkAtoms::letterFrame && aLineContainer->IsFloating()))', file /home/sgbowen/builds/mozilla-central/layout/generic/nsTextFrame.cpp, line 1259" which occasionally appears when opening pages with ruby or when running ruby reftests. Updates the manifest for ruby reftests to the current expectations (adjust assertion counts, etc.) --- layout/base/nsCSSFrameConstructor.cpp | 6 ++++-- layout/generic/nsRubyBaseContainerFrame.cpp | 12 ++++++++++++ layout/generic/nsRubyBaseContainerFrame.h | 2 ++ layout/generic/nsRubyBaseFrame.cpp | 6 ++++++ layout/generic/nsRubyBaseFrame.h | 1 + layout/generic/nsRubyFrame.cpp | 6 ++++++ layout/generic/nsRubyFrame.h | 1 + layout/generic/nsRubyTextFrame.cpp | 10 ---------- layout/generic/nsTextFrame.cpp | 6 ++++-- layout/reftests/css-ruby/reftest.list | 2 +- 10 files changed, 37 insertions(+), 15 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 115feae12b57..bdc9a4f18b89 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -4577,7 +4577,8 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay, FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer), NS_NewRubyBaseFrame) }, { NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER, - FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby), + FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | + FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby), NS_NewRubyBaseContainerFrame) }, { NS_STYLE_DISPLAY_RUBY_TEXT, FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | @@ -9105,7 +9106,8 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = { &nsCSSAnonBoxes::rubyBase }, { // Ruby Base Container - FCDATA_DECL(FCDATA_USE_CHILD_ITEMS | + FCDATA_DECL(FCDATA_USE_CHILD_ITEMS | + FCDATA_IS_LINE_PARTICIPANT | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby) | FCDATA_SKIP_FRAMESET, NS_NewRubyBaseContainerFrame), diff --git a/layout/generic/nsRubyBaseContainerFrame.cpp b/layout/generic/nsRubyBaseContainerFrame.cpp index b04c1184d506..814a92357f67 100644 --- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -52,6 +52,12 @@ nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const } #endif +/* virtual */ bool +nsRubyBaseContainerFrame::IsFrameOfType(uint32_t aFlags) const +{ + return nsContainerFrame::IsFrameOfType(aFlags & + ~(nsIFrame::eLineParticipant)); +} void nsRubyBaseContainerFrame::AppendTextContainer(nsIFrame* aFrame) { @@ -65,6 +71,12 @@ void nsRubyBaseContainerFrame::ClearTextContainers() { mTextContainers.Clear(); } +/* virtual */ bool +nsRubyBaseContainerFrame::CanContinueTextRun() const +{ + return true; +} + /* virtual */ void nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/generic/nsRubyBaseContainerFrame.h b/layout/generic/nsRubyBaseContainerFrame.h index 85a161b99c80..4e939d7d88ba 100644 --- a/layout/generic/nsRubyBaseContainerFrame.h +++ b/layout/generic/nsRubyBaseContainerFrame.h @@ -30,6 +30,8 @@ public: // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; + virtual bool CanContinueTextRun() const MOZ_OVERRIDE; virtual void Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, diff --git a/layout/generic/nsRubyBaseFrame.cpp b/layout/generic/nsRubyBaseFrame.cpp index 447a7c349bd0..005ccb0e29aa 100644 --- a/layout/generic/nsRubyBaseFrame.cpp +++ b/layout/generic/nsRubyBaseFrame.cpp @@ -95,6 +95,12 @@ nsRubyBaseFrame::GetLogicalBaseline(WritingMode aWritingMode) const return mBaseline; } +/* virtual */ bool +nsRubyBaseFrame::CanContinueTextRun() const +{ + return true; +} + /* virtual */ void nsRubyBaseFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/generic/nsRubyBaseFrame.h b/layout/generic/nsRubyBaseFrame.h index 33012cf20eb4..76a0ff388076 100644 --- a/layout/generic/nsRubyBaseFrame.h +++ b/layout/generic/nsRubyBaseFrame.h @@ -40,6 +40,7 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const MOZ_OVERRIDE; + virtual bool CanContinueTextRun() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; diff --git a/layout/generic/nsRubyFrame.cpp b/layout/generic/nsRubyFrame.cpp index 641a762b878c..f6b3d7c4b970 100644 --- a/layout/generic/nsRubyFrame.cpp +++ b/layout/generic/nsRubyFrame.cpp @@ -164,6 +164,12 @@ nsRubyFrame::GetLogicalBaseline(WritingMode aWritingMode) const return mBaseline; } +/* virtual */ bool +nsRubyFrame::CanContinueTextRun() const +{ + return true; +} + /* virtual */ void nsRubyFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/generic/nsRubyFrame.h b/layout/generic/nsRubyFrame.h index b9c9096d6bf1..bc88ce2ec424 100644 --- a/layout/generic/nsRubyFrame.h +++ b/layout/generic/nsRubyFrame.h @@ -38,6 +38,7 @@ public: nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const MOZ_OVERRIDE; + virtual bool CanContinueTextRun() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; diff --git a/layout/generic/nsRubyTextFrame.cpp b/layout/generic/nsRubyTextFrame.cpp index 06c5da11e917..9ea2753c1db5 100644 --- a/layout/generic/nsRubyTextFrame.cpp +++ b/layout/generic/nsRubyTextFrame.cpp @@ -75,9 +75,6 @@ nsRubyTextFrame::GetPrefISize(nsRenderingContext *aRenderingContext) nsRubyTextFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinISizeData *aData) { - // FIXME: See the fixme in AddInlinePrefISize. - aData->lineContainer = this; - for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { e.get()->AddInlineMinISize(aRenderingContext, aData); } @@ -87,13 +84,6 @@ nsRubyTextFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, nsRubyTextFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext, nsIFrame::InlinePrefISizeData *aData) { - // FIXME: We shouldn't need to set this, but it prevents us from tripping an - // assertion in nsTextFrame.cpp because FindLineContainer on a child frame will - // return the ruby text box (us) instead of the ruby text container (our - // parent). A fix would need to be made to FindLineContainer and/or - // CanContinueTextRun so that this line can be removed. - aData->lineContainer = this; - for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) { e.get()->AddInlinePrefISize(aRenderingContext, aData); } diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 9a17b1194090..3e04c2ea3d1d 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1026,7 +1026,8 @@ private: static nsIFrame* FindLineContainer(nsIFrame* aFrame) { - while (aFrame && aFrame->CanContinueTextRun()) { + while (aFrame && (aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || + aFrame->CanContinueTextRun())) { aFrame = aFrame->GetParent(); } return aFrame; @@ -1131,7 +1132,8 @@ CanTextCrossFrameBoundary(nsIFrame* aFrame, nsIAtom* aType) result.mScanSiblings = true; result.mTextRunCanCrossFrameBoundary = true; result.mLineBreakerCanCrossFrameBoundary = true; - } else if (aFrame->GetType() == nsGkAtoms::rubyTextFrame) { + } else if (aFrame->GetType() == nsGkAtoms::rubyTextFrame || + aFrame->GetType() == nsGkAtoms::rubyTextContainerFrame) { result.mFrameToScan = aFrame->GetFirstPrincipalChild(); result.mOverflowFrameToScan = aFrame->GetFirstChild(nsIFrame::kOverflowList); diff --git a/layout/reftests/css-ruby/reftest.list b/layout/reftests/css-ruby/reftest.list index 9a52cbf2599f..e734d18a1544 100644 --- a/layout/reftests/css-ruby/reftest.list +++ b/layout/reftests/css-ruby/reftest.list @@ -1,4 +1,4 @@ default-preferences pref(layout.css.ruby.enabled,true) -asserts(1) == ruby-whitespace-1.html ruby-whitespace-1-ref.html # bug 1052145 +fails asserts(3-7) == ruby-whitespace-1.html ruby-whitespace-1-ref.html # bug 1052924 == ruby-whitespace-2.html ruby-whitespace-2-ref.html From 4c005d254ac2ce9d61c499ef3b89a8e3ad3e35ad Mon Sep 17 00:00:00 2001 From: Susanna Bowen Date: Fri, 15 Aug 2014 10:34:20 -0700 Subject: [PATCH 48/86] Bug 1030993 - Reftests for Ruby reflow implementation.r=dbaron --- layout/reftests/css-ruby/reftest.list | 2 ++ .../css-ruby/ruby-reflow-1-noruby.html | 22 ++++++++++++++++ .../css-ruby/ruby-reflow-1-opaqueruby.html | 25 +++++++++++++++++++ .../ruby-reflow-1-transparentruby.html | 25 +++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 layout/reftests/css-ruby/ruby-reflow-1-noruby.html create mode 100644 layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html create mode 100644 layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html diff --git a/layout/reftests/css-ruby/reftest.list b/layout/reftests/css-ruby/reftest.list index e734d18a1544..331c98c2ed0d 100644 --- a/layout/reftests/css-ruby/reftest.list +++ b/layout/reftests/css-ruby/reftest.list @@ -2,3 +2,5 @@ default-preferences pref(layout.css.ruby.enabled,true) fails asserts(3-7) == ruby-whitespace-1.html ruby-whitespace-1-ref.html # bug 1052924 == ruby-whitespace-2.html ruby-whitespace-2-ref.html +asserts(0-1) != ruby-reflow-1-opaqueruby.html ruby-reflow-1-noruby.html # bug 1052924 +asserts(0-1) == ruby-reflow-1-transparentruby.html ruby-reflow-1-noruby.html # bug 1052924 diff --git a/layout/reftests/css-ruby/ruby-reflow-1-noruby.html b/layout/reftests/css-ruby/ruby-reflow-1-noruby.html new file mode 100644 index 000000000000..8e1cdb2c867b --- /dev/null +++ b/layout/reftests/css-ruby/ruby-reflow-1-noruby.html @@ -0,0 +1,22 @@ + + + +CSS Test: Ruby Base Frames Reflowed + + + + + + + +新幹線 + + diff --git a/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html b/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html new file mode 100644 index 000000000000..23258d28a065 --- /dev/null +++ b/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html @@ -0,0 +1,25 @@ + + + +CSS Test: Ruby Text Frames Visible + + + + + + + + + + しんかんせん + + + diff --git a/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html b/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html new file mode 100644 index 000000000000..88ebf819030d --- /dev/null +++ b/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html @@ -0,0 +1,25 @@ + + + +CSS Test: Ruby Base Frames Reflowed + + + + + + + + + + しんかんせん + + + From 6848a3e20c84c3299145ca990e5a0c43a677b542 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Fri, 15 Aug 2014 10:34:20 -0700 Subject: [PATCH 49/86] Bug 1030993 followup - Annotate ruby reftests directory as skip-if(B2G), pending investigation on followup bug. --- layout/reftests/reftest.list | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list index c7feb07f09b7..9e99bb9c7518 100644 --- a/layout/reftests/reftest.list +++ b/layout/reftests/reftest.list @@ -91,7 +91,8 @@ include css-parsing/reftest.list include css-placeholder/reftest.list # css ruby -include css-ruby/reftest.list +# (Skipping on B2G because of timeouts there; see bug 1054383) +skip-if(B2G) include css-ruby/reftest.list # css required include css-required/reftest.list From a945dc604f4cd958c9e1295d5fd2acd6f8122899 Mon Sep 17 00:00:00 2001 From: Shian-Yow Wu Date: Tue, 15 Jul 2014 03:02:00 -0700 Subject: [PATCH 50/86] Bug 1037358 - Pass the flag in setDataPointer() to indicate whether data is memory-mapped., r=Waldo --- js/src/shell/js.cpp | 4 +- js/src/vm/ArrayBufferObject.cpp | 199 ++++++++++++++++++-------------- js/src/vm/ArrayBufferObject.h | 106 ++++++++++++----- js/src/vm/SharedArrayObject.cpp | 2 +- js/src/vm/StructuredClone.cpp | 3 +- 5 files changed, 194 insertions(+), 120 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 0a56c5b99f69..cd01d4e9bc8d 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1056,7 +1056,9 @@ static bool CacheEntry_setBytecode(JSContext *cx, HandleObject cache, uint8_t *buffer, uint32_t length) { JS_ASSERT(CacheEntry_isCacheEntry(cache)); - Rooted arrayBuffer(cx, ArrayBufferObject::create(cx, length, buffer)); + ArrayBufferObject::BufferContents contents = + ArrayBufferObject::BufferContents::create(buffer); + Rooted arrayBuffer(cx, ArrayBufferObject::create(cx, length, contents)); if (!arrayBuffer || !ArrayBufferObject::ensureNonInline(cx, arrayBuffer)) return false; diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 2aaf5b34f246..5c9335de43d7 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -266,32 +266,35 @@ ArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value *vp) return true; } +static ArrayBufferObject::BufferContents +AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes) +{ + void *p = maybecx ? maybecx->runtime()->callocCanGC(nbytes) : js_calloc(nbytes); + if (!p && maybecx) + js_ReportOutOfMemory(maybecx); + + return ArrayBufferObject::BufferContents::create(p); +} + /* * Note that some callers are allowed to pass in a nullptr cx, so we allocate * with the cx if available and fall back to the runtime. If oldptr is given, * it's expected to be a previously-allocated contents pointer that we then * realloc. */ -static void * -AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr = nullptr, size_t oldnbytes = 0) +static ArrayBufferObject::BufferContents +ReallocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr, size_t oldnbytes) { - void *p; + void *p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, nbytes) : js_realloc(oldptr, nbytes); - // if oldptr is given, then we need to do a realloc - if (oldptr) { - p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, nbytes) : js_realloc(oldptr, nbytes); - - // if we grew the array, we need to set the new bytes to 0 - if (p && nbytes > oldnbytes) - memset(reinterpret_cast(p) + oldnbytes, 0, nbytes - oldnbytes); - } else { - p = maybecx ? maybecx->runtime()->callocCanGC(nbytes) : js_calloc(nbytes); - } + // if we grew the array, we need to set the new bytes to 0 + if (p && nbytes > oldnbytes) + memset(reinterpret_cast(p) + oldnbytes, 0, nbytes - oldnbytes); if (!p && maybecx) js_ReportOutOfMemory(maybecx); - return p; + return ArrayBufferObject::BufferContents::create(p); } ArrayBufferViewObject * @@ -330,7 +333,8 @@ ArrayBufferObject::canNeuter(JSContext *cx) } /* static */ void -ArrayBufferObject::neuter(JSContext *cx, Handle buffer, void *newData) +ArrayBufferObject::neuter(JSContext *cx, Handle buffer, + BufferContents newContents) { JS_ASSERT(buffer->canNeuter(cx)); @@ -338,14 +342,14 @@ ArrayBufferObject::neuter(JSContext *cx, Handle buffer, void // buffer's data. for (ArrayBufferViewObject *view = buffer->viewList(); view; view = view->nextView()) { - view->neuter(newData); + view->neuter(newContents.data()); // Notify compiled jit code that the base pointer has moved. MarkObjectStateChange(cx, view); } - if (newData != buffer->dataPointer()) - buffer->setNewOwnedData(cx->runtime()->defaultFreeOp(), newData); + if (newContents.data() != buffer->dataPointer()) + buffer->setNewOwnedData(cx->runtime()->defaultFreeOp(), newContents); buffer->setByteLength(0); buffer->setViewList(nullptr); @@ -370,25 +374,25 @@ ArrayBufferObject::neuter(JSContext *cx, Handle buffer, void } void -ArrayBufferObject::setNewOwnedData(FreeOp* fop, void *newData) +ArrayBufferObject::setNewOwnedData(FreeOp* fop, BufferContents newContents) { JS_ASSERT(!isAsmJSArrayBuffer()); JS_ASSERT(!isSharedArrayBuffer()); if (ownsData()) { - JS_ASSERT(newData != dataPointer()); + JS_ASSERT(newContents.data() != dataPointer()); releaseData(fop); } - setDataPointer(static_cast(newData), OwnsData); + setDataPointer(newContents, OwnsData); } void -ArrayBufferObject::changeContents(JSContext *cx, void *newData) +ArrayBufferObject::changeContents(JSContext *cx, BufferContents newContents) { // Change buffer contents. uint8_t* oldDataPointer = dataPointer(); - setNewOwnedData(cx->runtime()->defaultFreeOp(), newData); + setNewOwnedData(cx->runtime()->defaultFreeOp(), newContents); // Update all views. ArrayBufferViewObject *viewListHead = viewList(); @@ -398,9 +402,9 @@ ArrayBufferObject::changeContents(JSContext *cx, void *newData) // with the correct pointer). uint8_t *viewDataPointer = view->dataPointer(); if (viewDataPointer) { - JS_ASSERT(newData); + JS_ASSERT(newContents); ptrdiff_t offset = viewDataPointer - oldDataPointer; - viewDataPointer = static_cast(newData) + offset; + viewDataPointer = static_cast(newContents.data()) + offset; view->setPrivate(viewDataPointer); } @@ -433,7 +437,7 @@ ArrayBufferObject::prepareForAsmJSNoSignals(JSContext *cx, Handlefree_(dataPointer()); } @@ -488,22 +492,19 @@ ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle buf // Copy over the current contents of the typed array. memcpy(data, buffer->dataPointer(), buffer->byteLength()); - // Swap the new elements into the ArrayBufferObject. - buffer->changeContents(cx, data); + // Swap the new elements into the ArrayBufferObject. Mark the + // ArrayBufferObject so we don't do this again. + BufferContents newContents = BufferContents::create(data); + buffer->changeContents(cx, newContents); JS_ASSERT(data == buffer->dataPointer()); - // Mark the ArrayBufferObject so (1) we don't do this again, (2) we know not - // to js_free the data in the normal way. - buffer->setIsAsmJSArrayBuffer(); - buffer->setIsAsmJSMappedArrayBuffer(); - return true; } void ArrayBufferObject::releaseAsmJSArray(FreeOp *fop) { - if (!isAsmJSMappedArrayBuffer()) { + if (!(bufferKind() & MAPPED_BUFFER)) { releaseAsmJSArrayNoSignals(fop); return; } @@ -558,10 +559,11 @@ ArrayBufferObject::canNeuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &b return false; } -void * +ArrayBufferObject::BufferContents ArrayBufferObject::createMappedContents(int fd, size_t offset, size_t length) { - return AllocateMappedContent(fd, offset, length, ARRAY_BUFFER_ALIGNMENT); + void *data = AllocateMappedContent(fd, offset, length, ARRAY_BUFFER_ALIGNMENT); + return BufferContents::create(data); } void @@ -606,20 +608,22 @@ ArrayBufferObject::releaseData(FreeOp *fop) { JS_ASSERT(ownsData()); - if (isAsmJSArrayBuffer()) + BufferKind bufkind = bufferKind(); + if (bufkind & ASMJS_BUFFER) releaseAsmJSArray(fop); - else if (isMappedArrayBuffer()) + else if (bufkind & MAPPED_BUFFER) releaseMappedArray(); else fop->free_(dataPointer()); } void -ArrayBufferObject::setDataPointer(void *data, OwnsState ownsData) +ArrayBufferObject::setDataPointer(BufferContents contents, OwnsState ownsData) { - MOZ_ASSERT_IF(!is() && !isMappedArrayBuffer(), data != nullptr); - setSlot(DATA_SLOT, PrivateValue(data)); + MOZ_ASSERT_IF(!is(), contents.data()); + setSlot(DATA_SLOT, PrivateValue(contents.data())); setOwnsData(ownsData); + setFlags((flags() & ~KIND_MASK) | contents.kind()); } size_t @@ -647,11 +651,10 @@ ArrayBufferObject::setFlags(uint32_t flags) } ArrayBufferObject * -ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, void *data /* = nullptr */, - NewObjectKind newKind /* = GenericObject */, - bool mapped /* = false */) +ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, BufferContents contents, + NewObjectKind newKind /* = GenericObject */) { - JS_ASSERT_IF(mapped, data); + JS_ASSERT_IF(contents.kind() & MAPPED_BUFFER, contents); // If we need to allocate data, try to use a larger object size class so // that the array buffer's data can be allocated inline with the object. @@ -660,16 +663,19 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, void *data /* = nullpt size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&class_); size_t nslots = reservedSlots; - if (!data) { + bool allocated = false; + if (!contents) { size_t usableSlots = JSObject::MAX_FIXED_SLOTS - reservedSlots; if (nbytes <= usableSlots * sizeof(Value)) { int newSlots = (nbytes - 1) / sizeof(Value) + 1; JS_ASSERT(int(nbytes) <= newSlots * int(sizeof(Value))); nslots = reservedSlots + newSlots; + contents = BufferContents::createUnowned(nullptr); } else { - data = AllocateArrayBufferContents(cx, nbytes); - if (!data) + contents = AllocateArrayBufferContents(cx, nbytes); + if (!contents) return nullptr; + allocated = true; } } @@ -677,28 +683,35 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, void *data /* = nullpt gc::AllocKind allocKind = GetGCObjectKind(nslots); Rooted obj(cx, NewBuiltinClassInstance(cx, allocKind, newKind)); - if (!obj) + if (!obj) { + if (allocated) + js_free(contents.data()); return nullptr; + } JS_ASSERT(obj->getClass() == &class_); - JS_ASSERT(!gc::IsInsideNursery(obj)); - if (data) { - obj->initialize(nbytes, data, OwnsData); - if (mapped) - obj->setIsMappedArrayBuffer(); - if (mapped) - JS_updateMallocCounter(cx, JS_ROUNDUP(nbytes, js::gc::SystemPageSize())); - } else { + if (!contents) { void *data = obj->fixedData(reservedSlots); memset(data, 0, nbytes); - obj->initialize(nbytes, data, DoesntOwnData); + obj->initialize(nbytes, BufferContents::createUnowned(data), DoesntOwnData); + } else { + if (contents.kind() & MAPPED_BUFFER) + JS_updateMallocCounter(cx, JS_ROUNDUP(nbytes, js::gc::SystemPageSize())); + obj->initialize(nbytes, contents, OwnsData); } return obj; } +ArrayBufferObject * +ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, + NewObjectKind newKind /* = GenericObject */) +{ + return create(cx, nbytes, BufferContents::createUnowned(nullptr)); +} + JSObject * ArrayBufferObject::createSlice(JSContext *cx, Handle arrayBuffer, uint32_t begin, uint32_t end) @@ -756,11 +769,12 @@ ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp ArrayBufferObject::ensureNonInline(JSContext *cx, Handle buffer) { if (!buffer->ownsData()) { - void *data = AllocateArrayBufferContents(cx, buffer->byteLength()); - if (!data) + MOZ_ASSERT(!buffer->isSharedArrayBuffer()); + BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength()); + if (!contents) return false; - memcpy(data, buffer->dataPointer(), buffer->byteLength()); - buffer->changeContents(cx, data); + memcpy(contents.data(), buffer->dataPointer(), buffer->byteLength()); + buffer->changeContents(cx, contents); } return true; @@ -774,22 +788,25 @@ ArrayBufferObject::stealContents(JSContext *cx, Handle buffe return nullptr; } - void *oldData = buffer->dataPointer(); - void *newData = AllocateArrayBufferContents(cx, buffer->byteLength()); - if (!newData) + BufferContents oldContents(buffer->dataPointer(), buffer->bufferKind()); + BufferContents newContents = AllocateArrayBufferContents(cx, buffer->byteLength()); + if (!newContents) return nullptr; if (buffer->hasStealableContents()) { + // Return the old contents and give the neutered buffer a pointer to + // freshly allocated memory that we will never write to and should + // never get committed. buffer->setOwnsData(DoesntOwnData); - ArrayBufferObject::neuter(cx, buffer, newData); - return oldData; + ArrayBufferObject::neuter(cx, buffer, newContents); + return oldContents.data(); } else { - memcpy(newData, oldData, buffer->byteLength()); - ArrayBufferObject::neuter(cx, buffer, oldData); - return newData; + // Create a new chunk of memory to return since we cannot steal the + // existing contents away from the buffer. + memcpy(newContents.data(), oldContents.data(), buffer->byteLength()); + ArrayBufferObject::neuter(cx, buffer, oldContents); + return newContents.data(); } - - return oldData; } /* static */ void @@ -800,14 +817,14 @@ ArrayBufferObject::addSizeOfExcludingThis(JSObject *obj, mozilla::MallocSizeOf m if (!buffer.ownsData()) return; - if (MOZ_UNLIKELY(buffer.isAsmJSArrayBuffer())) { + if (MOZ_UNLIKELY(buffer.bufferKind() & ASMJS_BUFFER)) { // On x64, ArrayBufferObject::prepareForAsmJS switches the // ArrayBufferObject to use mmap'd storage. - if (buffer.isAsmJSMappedArrayBuffer()) + if (buffer.bufferKind() & MAPPED_BUFFER) sizes->nonHeapElementsAsmJS += buffer.byteLength(); else sizes->mallocHeapElementsAsmJS += mallocSizeOf(buffer.dataPointer()); - } else if (MOZ_UNLIKELY(buffer.isMappedArrayBuffer())) { + } else if (MOZ_UNLIKELY(buffer.bufferKind() & MAPPED_BUFFER)) { sizes->nonHeapElementsMapped += buffer.byteLength(); } else if (buffer.dataPointer()) { sizes->mallocHeapElementsNonAsmJS += mallocSizeOf(buffer.dataPointer()); @@ -1099,16 +1116,16 @@ JS_NeuterArrayBuffer(JSContext *cx, HandleObject obj, return false; } - void *newData; if (changeData == ChangeData && buffer->hasStealableContents()) { - newData = AllocateArrayBufferContents(cx, buffer->byteLength()); - if (!newData) + ArrayBufferObject::BufferContents newContents = + AllocateArrayBufferContents(cx, buffer->byteLength()); + if (!newContents) return false; + ArrayBufferObject::neuter(cx, buffer, newContents); } else { - newData = buffer->dataPointer(); + ArrayBufferObject::neuter(cx, buffer, buffer->contents()); } - ArrayBufferObject::neuter(cx, buffer, newData); return true; } @@ -1132,22 +1149,24 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes) } JS_PUBLIC_API(JSObject *) -JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *contents) +JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *data) { - JS_ASSERT(contents); - return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject, false); + JS_ASSERT(data); + ArrayBufferObject::BufferContents contents = + ArrayBufferObject::BufferContents::create(data); + return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject); } JS_PUBLIC_API(void *) JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes) { - return AllocateArrayBufferContents(maybecx, nbytes); + return AllocateArrayBufferContents(maybecx, nbytes).data(); } JS_PUBLIC_API(void *) JS_ReallocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldContents, uint32_t oldNbytes) { - return AllocateArrayBufferContents(maybecx, nbytes, oldContents, oldNbytes); + return ReallocateArrayBufferContents(maybecx, nbytes, oldContents, oldNbytes).data(); } JS_FRIEND_API(bool) @@ -1182,16 +1201,18 @@ JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg) } JS_PUBLIC_API(JSObject *) -JS_NewMappedArrayBufferWithContents(JSContext *cx, size_t nbytes, void *contents) +JS_NewMappedArrayBufferWithContents(JSContext *cx, size_t nbytes, void *data) { - JS_ASSERT(contents); - return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject, true); + JS_ASSERT(data); + ArrayBufferObject::BufferContents contents = + ArrayBufferObject::BufferContents::create(data); + return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject); } JS_PUBLIC_API(void *) JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length) { - return ArrayBufferObject::createMappedContents(fd, offset, length); + return ArrayBufferObject::createMappedContents(fd, offset, length).data(); } JS_PUBLIC_API(void) diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index 8bf20bc76584..cea82ae6ca3d 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -62,6 +62,68 @@ class ArrayBufferObject : public JSObject static const size_t ARRAY_BUFFER_ALIGNMENT = 8; + public: + + enum BufferKind { + PLAIN_BUFFER = 0, // malloced or inline data + ASMJS_BUFFER = 0x1, + SHARED_BUFFER = 0x2, + MAPPED_BUFFER = 0x4, + KIND_MASK = ASMJS_BUFFER | SHARED_BUFFER | MAPPED_BUFFER + }; + + protected: + + enum ArrayBufferFlags { + // The flags also store the BufferKind + BUFFER_KIND_MASK = BufferKind::KIND_MASK, + + NEUTERED_BUFFER = 0x8, + + // In the gcLiveArrayBuffers list. + IN_LIVE_LIST = 0x10, + + // The dataPointer() is owned by this buffer and should be released + // when no longer in use. Releasing the pointer may be done by either + // freeing or unmapping it, and how to do this is determined by the + // buffer's other flags. + OWNS_DATA = 0x20, + }; + + public: + + class BufferContents { + uint8_t *data_; + BufferKind kind_; + + friend class ArrayBufferObject; + + typedef void (BufferContents::* ConvertibleToBool)(); + void nonNull() {} + + BufferContents(uint8_t *data, BufferKind kind) : data_(data), kind_(kind) { + MOZ_ASSERT((kind_ & ~KIND_MASK) == 0); + } + + public: + + template + static BufferContents create(void *data) + { + return BufferContents(static_cast(data), Kind); + } + + static BufferContents createUnowned(void *data) + { + return BufferContents(static_cast(data), PLAIN_BUFFER); + } + + uint8_t *data() const { return data_; } + BufferKind kind() const { return kind_; } + + operator ConvertibleToBool() const { return data_ ? &BufferContents::nonNull : nullptr; } + }; + static const Class class_; static const Class protoClass; @@ -76,8 +138,11 @@ class ArrayBufferObject : public JSObject static bool class_constructor(JSContext *cx, unsigned argc, Value *vp); - static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, void *contents = nullptr, - NewObjectKind newKind = GenericObject, bool mapped = false); + static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, + BufferContents contents, + NewObjectKind newKind = GenericObject); + static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, + NewObjectKind newKind = GenericObject); static JSObject *createSlice(JSContext *cx, Handle arrayBuffer, uint32_t begin, uint32_t end); @@ -126,8 +191,8 @@ class ArrayBufferObject : public JSObject void addView(ArrayBufferViewObject *view); - void setNewOwnedData(FreeOp* fop, void *newData); - void changeContents(JSContext *cx, void *newData); + void setNewOwnedData(FreeOp* fop, BufferContents newContents); + void changeContents(JSContext *cx, BufferContents newContents); /* * Ensure data is not stored inline in the object. Used when handing back a @@ -138,10 +203,13 @@ class ArrayBufferObject : public JSObject bool canNeuter(JSContext *cx); /* Neuter this buffer and all its views. */ - static void neuter(JSContext *cx, Handle buffer, void *newData); + static void neuter(JSContext *cx, Handle buffer, BufferContents newContents); uint8_t *dataPointer() const; size_t byteLength() const; + BufferContents contents() const { + return BufferContents(dataPointer(), bufferKind()); + } void releaseData(FreeOp *fop); @@ -153,8 +221,8 @@ class ArrayBufferObject : public JSObject return getClass() == &class_; } + BufferKind bufferKind() const { return BufferKind(flags() & BUFFER_KIND_MASK); } bool isAsmJSArrayBuffer() const { return flags() & ASMJS_BUFFER; } - bool isAsmJSMappedArrayBuffer() const { return flags() & ASMJS_MAPPED_BUFFER; } bool isSharedArrayBuffer() const { return flags() & SHARED_BUFFER; } bool isMappedArrayBuffer() const { return flags() & MAPPED_BUFFER; } bool isNeutered() const { return flags() & NEUTERED_BUFFER; } @@ -166,7 +234,7 @@ class ArrayBufferObject : public JSObject static void finalize(FreeOp *fop, JSObject *obj); - static void *createMappedContents(int fd, size_t offset, size_t length); + static BufferContents createMappedContents(int fd, size_t offset, size_t length); static size_t flagsOffset() { return getFixedSlotOffset(FLAGS_SLOT); @@ -180,30 +248,13 @@ class ArrayBufferObject : public JSObject OwnsData = 1, }; - void setDataPointer(void *data, OwnsState ownsState); + void setDataPointer(BufferContents contents, OwnsState ownsState); void setByteLength(size_t length); ArrayBufferViewObject *viewList() const; void setViewList(ArrayBufferViewObject *viewsHead); void setViewListNoBarrier(ArrayBufferViewObject *viewsHead); - enum ArrayBufferFlags { - // In the gcLiveArrayBuffers list. - IN_LIVE_LIST = 0x1, - - // The dataPointer() is owned by this buffer and should be released - // when no longer in use. Releasing the pointer may be done by either - // freeing or unmapping it, and how to do this is determined by the - // buffer's other flags. - OWNS_DATA = 0x2, - - ASMJS_BUFFER = 0x4, - ASMJS_MAPPED_BUFFER = 0x8, - SHARED_BUFFER = 0x10, - MAPPED_BUFFER = 0x20, - NEUTERED_BUFFER = 0x40, - }; - uint32_t flags() const; void setFlags(uint32_t flags); @@ -218,16 +269,15 @@ class ArrayBufferObject : public JSObject } void setIsAsmJSArrayBuffer() { setFlags(flags() | ASMJS_BUFFER); } - void setIsAsmJSMappedArrayBuffer() { setFlags(flags() | ASMJS_MAPPED_BUFFER); } void setIsSharedArrayBuffer() { setFlags(flags() | SHARED_BUFFER); } void setIsMappedArrayBuffer() { setFlags(flags() | MAPPED_BUFFER); } void setIsNeutered() { setFlags(flags() | NEUTERED_BUFFER); } - void initialize(size_t byteLength, void *data, OwnsState ownsState) { + void initialize(size_t byteLength, BufferContents contents, OwnsState ownsState) { setByteLength(byteLength); setFlags(0); setViewListNoBarrier(nullptr); - setDataPointer(data, ownsState); + setDataPointer(contents, ownsState); } void releaseAsmJSArray(FreeOp *fop); diff --git a/js/src/vm/SharedArrayObject.cpp b/js/src/vm/SharedArrayObject.cpp index 09775f89b5ae..f96b8027d78c 100644 --- a/js/src/vm/SharedArrayObject.cpp +++ b/js/src/vm/SharedArrayObject.cpp @@ -212,7 +212,7 @@ SharedArrayBufferObject::New(JSContext *cx, SharedArrayRawBuffer *buffer) JS_ASSERT(obj->getClass() == &class_); - obj->initialize(buffer->byteLength(), nullptr, DoesntOwnData); + obj->initialize(buffer->byteLength(), BufferContents::createUnowned(nullptr), DoesntOwnData); obj->acceptRawBuffer(buffer); obj->setIsSharedArrayBuffer(); diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index a9aa5816954e..b381f7d79f2c 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -1107,12 +1107,13 @@ JSStructuredCloneWriter::transferOwnership() #endif if (obj->is()) { + bool isMapped = obj->as().isMappedArrayBuffer(); size_t nbytes = obj->as().byteLength(); content = JS_StealArrayBufferContents(context(), obj); if (!content) return false; // Destructor will clean up the already-transferred data tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER; - if (obj->as().isMappedArrayBuffer()) + if (isMapped) ownership = JS::SCTAG_TMO_MAPPED_DATA; else ownership = JS::SCTAG_TMO_ALLOC_DATA; From 5626bfe92f614e7bd585eabdcc51e733fcdd663d Mon Sep 17 00:00:00 2001 From: Ed Lee Date: Fri, 15 Aug 2014 02:40:20 -0700 Subject: [PATCH 51/86] Bug 1026561 - The New Tab Page should be smarter about showing more tiles when on large screens [r=adw] Bump up default columns to fit most Firefox users including 2560px wide resolutions. --- browser/app/profile/firefox.js | 2 +- .../base/content/test/newtab/browser_newtab_bug752841.js | 4 ++-- .../content/test/newtab/browser_newtab_drag_drop_ext.js | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 522b708f72aa..3b5227456fc7 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1522,7 +1522,7 @@ pref("browser.newtabpage.enhanced", false); pref("browser.newtabpage.rows", 3); // number of columns of newtab grid -pref("browser.newtabpage.columns", 3); +pref("browser.newtabpage.columns", 8); // directory tiles download URL pref("browser.newtabpage.directory.source", "chrome://global/content/directoryLinks.json"); diff --git a/browser/base/content/test/newtab/browser_newtab_bug752841.js b/browser/base/content/test/newtab/browser_newtab_bug752841.js index 91c347b0c8d6..c19272417cae 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug752841.js +++ b/browser/base/content/test/newtab/browser_newtab_bug752841.js @@ -17,8 +17,8 @@ function runTests() { // Expected length of grid let expectedValues = [1, 1, 1, 1, 8, 10]; - // Values before setting new pref values (9 is the default value -> 3 x 3) - let previousValues = [9, 1, 1, 1, 1, 8]; + // Values before setting new pref values (24 is the default value -> 8 x 3) + let previousValues = [24, 1, 1, 1, 1, 8]; let existingTab, existingTabGridLength, newTab, newTabGridLength; yield addNewTabPageTab(); diff --git a/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js b/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js index 1ba7cfed8be2..11dc4dfda2ab 100644 --- a/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js +++ b/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns"; + /* * These tests make sure that dragging and dropping sites works as expected. * Sites contained in the grid need to shift around to indicate the result @@ -28,8 +30,11 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7p,8p"); + // force the grid to be small enough that a pinned cell could be pushed out + Services.prefs.setIntPref(PREF_NEWTAB_COLUMNS, 3); yield simulateExternalDrop(7); checkGrid("0,1,2,3,4,5,7p,99p,8p"); + Services.prefs.clearUserPref(PREF_NEWTAB_COLUMNS); // drag a new site beneath a pinned cell and make sure the pinned cell is // not moved @@ -52,4 +57,4 @@ function runTests() { yield simulateExternalDrop(1); checkGrid("0p,99p,1p,2p,3,4,5,6,7"); -} \ No newline at end of file +} From 5d23c803c553c0900af5e406c9dc775bdbc5a9d3 Mon Sep 17 00:00:00 2001 From: Mark Banner Date: Fri, 15 Aug 2014 13:33:51 +0100 Subject: [PATCH 52/86] Bug 1022594 Part 1a Add a getLoopBoolPref function to the MozLoopAPI. r=mikedeboer --HG-- rename : browser/components/loop/test/mochitest/browser_mozLoop_charPref.js => browser/components/loop/test/mochitest/browser_mozLoop_prefs.js rename : browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js => browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js --- browser/components/loop/MozLoopAPI.jsm | 21 ++++ browser/components/loop/MozLoopService.jsm | 23 ++++ .../loop/test/mochitest/browser.ini | 2 +- ...p_charPref.js => browser_mozLoop_prefs.js} | 14 +++ .../test_loopservice_get_loop_char_pref.js | 47 -------- .../xpcshell/test_loopservice_loop_prefs.js | 106 ++++++++++++++++++ .../test_loopservice_set_loop_char_pref.js | 49 -------- .../loop/test/xpcshell/xpcshell.ini | 3 +- 8 files changed, 166 insertions(+), 99 deletions(-) rename browser/components/loop/test/mochitest/{browser_mozLoop_charPref.js => browser_mozLoop_prefs.js} (66%) delete mode 100644 browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js create mode 100644 browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js delete mode 100644 browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index 5c65efb9a906..4b91874f308d 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -160,6 +160,27 @@ function injectLoopAPI(targetWindow) { } }, + /** + * Return any preference under "loop." that's coercible to a boolean + * preference. + * + * @param {String} prefName The name of the pref without the preceding + * "loop." + * + * Any errors thrown by the Mozilla pref API are logged to the console + * and cause null to be returned. This includes the case of the preference + * not being found. + * + * @return {String} on success, null on error + */ + getLoopBoolPref: { + enumerable: true, + writable: true, + value: function(prefName) { + return MozLoopService.getLoopBoolPref(prefName); + } + }, + /** * Starts alerting the user about an incoming call */ diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index a9b2c417d177..7f1c611f8638 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -613,6 +613,29 @@ this.MozLoopService = { } }, + /** + * Return any preference under "loop." that's coercible to a character + * preference. + * + * @param {String} prefName The name of the pref without the preceding + * "loop." + * + * Any errors thrown by the Mozilla pref API are logged to the console + * and cause null to be returned. This includes the case of the preference + * not being found. + * + * @return {String} on success, null on error + */ + getLoopBoolPref: function(prefName) { + try { + return Services.prefs.getBoolPref("loop." + prefName); + } catch (ex) { + console.log("getLoopBoolPref had trouble getting " + prefName + + "; exception: " + ex); + return null; + } + }, + /** * Performs a hawk based request to the loop server. * diff --git a/browser/components/loop/test/mochitest/browser.ini b/browser/components/loop/test/mochitest/browser.ini index 15d82239682a..780e76aae23b 100644 --- a/browser/components/loop/test/mochitest/browser.ini +++ b/browser/components/loop/test/mochitest/browser.ini @@ -3,6 +3,6 @@ support-files = head.js [browser_mozLoop_appVersionInfo.js] -[browser_mozLoop_charPref.js] +[browser_mozLoop_prefs.js] [browser_mozLoop_doNotDisturb.js] skip-if = buildapp == 'mulet' diff --git a/browser/components/loop/test/mochitest/browser_mozLoop_charPref.js b/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js similarity index 66% rename from browser/components/loop/test/mochitest/browser_mozLoop_charPref.js rename to browser/components/loop/test/mochitest/browser_mozLoop_prefs.js index 8e8ef7ddacb4..a669d27cfccc 100644 --- a/browser/components/loop/test/mochitest/browser_mozLoop_charPref.js +++ b/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js @@ -24,3 +24,17 @@ add_task(function* test_mozLoop_charPref() { Assert.equal(gMozLoopAPI.getLoopCharPref("test"), "foo", "should get loop pref value correctly"); }); + +add_task(function* test_mozLoop_boolPref() { + registerCleanupFunction(function () { + Services.prefs.clearUserPref("loop.testBool"); + }); + + Assert.ok(gMozLoopAPI, "mozLoop should exist"); + + Services.prefs.setBoolPref("loop.testBool", true); + + // Test getLoopCharPref + Assert.equal(gMozLoopAPI.getLoopBoolPref("testBool"), true, + "should get loop pref value correctly"); +}); diff --git a/browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js b/browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js deleted file mode 100644 index f2f0230eaef2..000000000000 --- a/browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js +++ /dev/null @@ -1,47 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -/*global XPCOMUtils, Services, Assert */ - -var fakePrefName = "color"; -var fakePrefValue = "green"; - -function test_getLoopCharPref() -{ - Services.prefs.setCharPref("loop." + fakePrefName, fakePrefValue); - - var returnedPref = MozLoopService.getLoopCharPref(fakePrefName); - - Assert.equal(returnedPref, fakePrefValue, - "Should return a char pref under the loop. branch"); - Services.prefs.clearUserPref("loop." + fakePrefName); -} - -function test_getLoopCharPref_not_found() -{ - var returnedPref = MozLoopService.getLoopCharPref(fakePrefName); - - Assert.equal(returnedPref, null, - "Should return null if a preference is not found"); -} - -function test_getLoopCharPref_non_coercible_type() -{ - Services.prefs.setBoolPref("loop." + fakePrefName, false ); - - var returnedPref = MozLoopService.getLoopCharPref(fakePrefName); - - Assert.equal(returnedPref, null, - "Should return null if the preference exists & is of a non-coercible type"); -} - - -function run_test() -{ - test_getLoopCharPref(); - test_getLoopCharPref_not_found(); - test_getLoopCharPref_non_coercible_type(); - - do_register_cleanup(function() { - Services.prefs.clearUserPref("loop." + fakePrefName); - }); -} diff --git a/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js b/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js new file mode 100644 index 000000000000..c9af9a6a4dcd --- /dev/null +++ b/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js @@ -0,0 +1,106 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +/*global XPCOMUtils, Services, Assert */ + +var fakeCharPrefName = "color"; +var fakeBoolPrefName = "boolean"; +var fakePrefValue = "green"; + +function test_getLoopCharPref() +{ + Services.prefs.setCharPref("loop." + fakeCharPrefName, fakePrefValue); + + var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + + Assert.equal(returnedPref, fakePrefValue, + "Should return a char pref under the loop. branch"); + Services.prefs.clearUserPref("loop." + fakeCharPrefName); +} + +function test_getLoopCharPref_not_found() +{ + var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + + Assert.equal(returnedPref, null, + "Should return null if a preference is not found"); +} + +function test_getLoopCharPref_non_coercible_type() +{ + Services.prefs.setBoolPref("loop." + fakeCharPrefName, false); + + var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName); + + Assert.equal(returnedPref, null, + "Should return null if the preference exists & is of a non-coercible type"); +} + +function test_setLoopCharPref() +{ + Services.prefs.setCharPref("loop." + fakeCharPrefName, "red"); + MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue); + + var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName); + + Assert.equal(returnedPref, fakePrefValue, + "Should set a char pref under the loop. branch"); + Services.prefs.clearUserPref("loop." + fakeCharPrefName); +} + +function test_setLoopCharPref_new() +{ + Services.prefs.clearUserPref("loop." + fakeCharPrefName); + MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue); + + var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName); + + Assert.equal(returnedPref, fakePrefValue, + "Should set a new char pref under the loop. branch"); + Services.prefs.clearUserPref("loop." + fakeCharPrefName); +} + +function test_setLoopCharPref_non_coercible_type() +{ + MozLoopService.setLoopCharPref(fakeCharPrefName, true); + + ok(true, "Setting non-coercible type should not fail"); +} + + +function test_getLoopBoolPref() +{ + Services.prefs.setBoolPref("loop." + fakeBoolPrefName, true); + + var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName); + + Assert.equal(returnedPref, true, + "Should return a bool pref under the loop. branch"); + Services.prefs.clearUserPref("loop." + fakeBoolPrefName); +} + +function test_getLoopBoolPref_not_found() +{ + var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName); + + Assert.equal(returnedPref, null, + "Should return null if a preference is not found"); +} + + +function run_test() +{ + test_getLoopCharPref(); + test_getLoopCharPref_not_found(); + test_getLoopCharPref_non_coercible_type(); + test_setLoopCharPref(); + test_setLoopCharPref_new(); + test_setLoopCharPref_non_coercible_type(); + + test_getLoopBoolPref(); + test_getLoopBoolPref_not_found(); + + do_register_cleanup(function() { + Services.prefs.clearUserPref("loop." + fakeCharPrefName); + Services.prefs.clearUserPref("loop." + fakeBoolPrefName); + }); +} diff --git a/browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js b/browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js deleted file mode 100644 index 98213588b4f5..000000000000 --- a/browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js +++ /dev/null @@ -1,49 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -/*global XPCOMUtils, Services, Assert */ - -var fakePrefName = "color"; -var fakePrefValue = "green"; - -function test_setLoopCharPref() -{ - Services.prefs.setCharPref("loop." + fakePrefName, "red"); - MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue); - - var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName); - - Assert.equal(returnedPref, fakePrefValue, - "Should set a char pref under the loop. branch"); - Services.prefs.clearUserPref("loop." + fakePrefName); -} - -function test_setLoopCharPref_new() -{ - Services.prefs.clearUserPref("loop." + fakePrefName); - MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue); - - var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName); - - Assert.equal(returnedPref, fakePrefValue, - "Should set a new char pref under the loop. branch"); - Services.prefs.clearUserPref("loop." + fakePrefName); -} - -function test_setLoopCharPref_non_coercible_type() -{ - MozLoopService.setLoopCharPref(fakePrefName, true); - - ok(true, "Setting non-coercible type should not fail"); -} - - -function run_test() -{ - test_setLoopCharPref(); - test_setLoopCharPref_new(); - test_setLoopCharPref_non_coercible_type(); - - do_register_cleanup(function() { - Services.prefs.clearUserPref("loop." + fakePrefName); - }); -} diff --git a/browser/components/loop/test/xpcshell/xpcshell.ini b/browser/components/loop/test/xpcshell/xpcshell.ini index 95bfa172646a..5ad16005a4fe 100644 --- a/browser/components/loop/test/xpcshell/xpcshell.ini +++ b/browser/components/loop/test/xpcshell/xpcshell.ini @@ -6,8 +6,7 @@ firefox-appdir = browser [test_looppush_initialize.js] [test_loopservice_dnd.js] [test_loopservice_expiry.js] -[test_loopservice_get_loop_char_pref.js] -[test_loopservice_set_loop_char_pref.js] +[test_loopservice_loop_prefs.js] [test_loopservice_initialize.js] [test_loopservice_locales.js] [test_loopservice_registration.js] From 7e27415cca407e71fdf2f5c62f3ff6c9fe557933 Mon Sep 17 00:00:00 2001 From: Brian Grinstead Date: Fri, 15 Aug 2014 07:50:43 -0500 Subject: [PATCH 53/86] Bug 1050439 - Focus should be restored to previously active element after split console is closed;r=jwalker --- browser/devtools/framework/toolbox.js | 31 +++++++- browser/devtools/webconsole/test/browser.ini | 1 + .../test/browser_webconsole_split_focus.js | 74 +++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 browser/devtools/webconsole/test/browser_webconsole_split_focus.js diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index 3afa78dd2b2f..d8fb23518b94 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -76,6 +76,7 @@ function Toolbox(target, selectedTool, hostType, hostOptions) { this._highlighterHidden = this._highlighterHidden.bind(this); this._prefChanged = this._prefChanged.bind(this); this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this); + this._onFocus = this._onFocus.bind(this); this._target.on("close", this.destroy); @@ -253,7 +254,7 @@ Toolbox.prototype = { this._applyCacheSettings(); this._addKeysToWindow(); this._addReloadKeys(); - this._addToolSwitchingKeys(); + this._addHostListeners(); this._addZoomKeys(); this._loadInitialZoom(); @@ -345,7 +346,7 @@ Toolbox.prototype = { }); }, - _addToolSwitchingKeys: function() { + _addHostListeners: function() { let nextKey = this.doc.getElementById("toolbox-next-tool-key"); nextKey.addEventListener("command", this.selectNextTool.bind(this), true); let prevKey = this.doc.getElementById("toolbox-previous-tool-key"); @@ -354,6 +355,8 @@ Toolbox.prototype = { // Split console uses keypress instead of command so the event can be // cancelled with stopPropagation on the keypress, and not preventDefault. this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false); + + this.doc.addEventListener("focus", this._onFocus, true); }, _saveSplitConsoleHeight: function() { @@ -982,6 +985,23 @@ Toolbox.prototype = { } }, + /** + * If the console is split and we are focusing an element outside + * of the console, then store the newly focused element, so that + * it can be restored once the split console closes. + */ + _onFocus: function({originalTarget}) { + // Ignore any non element nodes, or any elements contained + // within the webconsole frame. + let webconsoleURL = gDevTools.getToolDefinition("webconsole").url; + if (originalTarget.nodeType !== 1 || + originalTarget.baseURI === webconsoleURL) { + return; + } + + this._lastFocusedElement = originalTarget; + }, + /** * Opens the split console. * @@ -993,6 +1013,7 @@ Toolbox.prototype = { Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, true); this._refreshConsoleDisplay(); this.emit("split-console"); + return this.loadTool("webconsole").then(() => { this.focusConsoleInput(); }); @@ -1009,6 +1030,10 @@ Toolbox.prototype = { Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, false); this._refreshConsoleDisplay(); this.emit("split-console"); + + if (this._lastFocusedElement) { + this._lastFocusedElement.focus(); + } return promise.resolve(); }, @@ -1312,6 +1337,7 @@ Toolbox.prototype = { destroyHost: function() { this.doc.removeEventListener("keypress", this._splitConsoleOnKeypress, false); + this.doc.removeEventListener("focus", this._onFocus, true); return this._host.destroy(); }, @@ -1334,6 +1360,7 @@ Toolbox.prototype = { gDevTools.off("pref-changed", this._prefChanged); + this._lastFocusedElement = null; this._saveSplitConsoleHeight(); this.webconsolePanel.removeEventListener("resize", this._saveSplitConsoleHeight); diff --git a/browser/devtools/webconsole/test/browser.ini b/browser/devtools/webconsole/test/browser.ini index 32ddf719fd6e..1627ccc34b66 100644 --- a/browser/devtools/webconsole/test/browser.ini +++ b/browser/devtools/webconsole/test/browser.ini @@ -281,6 +281,7 @@ skip-if = buildapp == 'mulet' [browser_webconsole_scratchpad_panel_link.js] [browser_webconsole_split.js] [browser_webconsole_split_escape_key.js] +[browser_webconsole_split_focus.js] [browser_webconsole_split_persist.js] [browser_webconsole_view_source.js] [browser_webconsole_reflow.js] diff --git a/browser/devtools/webconsole/test/browser_webconsole_split_focus.js b/browser/devtools/webconsole/test/browser_webconsole_split_focus.js new file mode 100644 index 000000000000..3246311074c7 --- /dev/null +++ b/browser/devtools/webconsole/test/browser_webconsole_split_focus.js @@ -0,0 +1,74 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function test() { + info("Test that the split console state is persisted"); + + let toolbox; + let TEST_URI = "data:text/html;charset=utf-8,

Web Console test for splitting

"; + + Task.spawn(runner).then(finish); + + function* runner() { + info("Opening a tab while there is no user setting on split console pref"); + let {tab} = yield loadTab(TEST_URI); + let target = TargetFactory.forTab(tab); + toolbox = yield gDevTools.showToolbox(target, "inspector"); + + ok(!toolbox.splitConsole, "Split console is hidden by default"); + + info ("Focusing the search box before opening the split console"); + let inspector = toolbox.getPanel("inspector"); + inspector.searchBox.focus(); + + // Use the binding element since inspector.searchBox is a XUL element. + let activeElement = getActiveElement(inspector.panelDoc); + activeElement = activeElement.ownerDocument.getBindingParent(activeElement); + is (activeElement, inspector.searchBox, "Search box is focused"); + + yield toolbox.openSplitConsole(); + + ok(toolbox.splitConsole, "Split console is now visible"); + + // Use the binding element since jsterm.inputNode is a XUL textarea element. + let activeElement = getActiveElement(toolbox.doc); + activeElement = activeElement.ownerDocument.getBindingParent(activeElement); + let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode; + is(activeElement, inputNode, "Split console input is focused by default"); + + yield toolbox.closeSplitConsole(); + + info ("Making sure that the search box is refocused after closing the split console"); + // Use the binding element since inspector.searchBox is a XUL element. + let activeElement = getActiveElement(inspector.panelDoc); + activeElement = activeElement.ownerDocument.getBindingParent(activeElement); + is (activeElement, inspector.searchBox, "Search box is focused"); + + yield toolbox.destroy(); + } + + function getActiveElement(doc) { + let activeElement = doc.activeElement; + while (activeElement && activeElement.contentDocument) { + activeElement = activeElement.contentDocument.activeElement; + } + return activeElement; + } + + function toggleSplitConsoleWithEscape() { + let onceSplitConsole = toolbox.once("split-console"); + let contentWindow = toolbox.frame.contentWindow; + contentWindow.focus(); + EventUtils.sendKey("ESCAPE", contentWindow); + return onceSplitConsole; + } + + function finish() { + toolbox = TEST_URI = null; + Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled"); + Services.prefs.clearUserPref("devtools.toolbox.splitconsoleHeight"); + finishTest(); + } +} From d64b0cbea43a9305cf445f31f4abe913fe09e91f Mon Sep 17 00:00:00 2001 From: Brian Grinstead Date: Fri, 15 Aug 2014 07:52:08 -0500 Subject: [PATCH 54/86] Bug 1050442 - If persisted, focus split console input when toolbox opens;r=jwalker --- browser/devtools/framework/toolbox.js | 19 +++++++++++-------- .../test/browser_webconsole_split_persist.js | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index d8fb23518b94..b7465570eed1 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -264,16 +264,19 @@ Toolbox.prototype = { this.webconsolePanel.addEventListener("resize", this._saveSplitConsoleHeight); - let splitConsolePromise = promise.resolve(); - if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) { - splitConsolePromise = this.openSplitConsole(); - } - let buttonsPromise = this._buildButtons(); this._telemetry.toolOpened("toolbox"); this.selectTool(this._defaultToolId).then(panel => { + + // Wait until the original tool is selected so that the split + // console input will receive focus. + let splitConsolePromise = promise.resolve(); + if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) { + splitConsolePromise = this.openSplitConsole(); + } + promise.all([ splitConsolePromise, buttonsPromise @@ -979,9 +982,9 @@ Toolbox.prototype = { * Focus split console's input line */ focusConsoleInput: function() { - let hud = this.getPanel("webconsole").hud; - if (hud && hud.jsterm) { - hud.jsterm.inputNode.focus(); + let consolePanel = this.getPanel("webconsole"); + if (consolePanel) { + consolePanel.focusInput(); } }, diff --git a/browser/devtools/webconsole/test/browser_webconsole_split_persist.js b/browser/devtools/webconsole/test/browser_webconsole_split_persist.js index 42997df0f948..69534d81bb36 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_split_persist.js +++ b/browser/devtools/webconsole/test/browser_webconsole_split_persist.js @@ -35,6 +35,12 @@ function test() { ok(toolbox.splitConsole, "Split console is visible by default."); is(getHeightPrefValue(), 200, "Height is set based on panel height after closing"); + // Use the binding element since jsterm.inputNode is a XUL textarea element. + let activeElement = getActiveElement(toolbox.doc); + activeElement = activeElement.ownerDocument.getBindingParent(activeElement); + let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode; + is(activeElement, inputNode, "Split console input is focused by default"); + toolbox.webconsolePanel.height = 1; ok (toolbox.webconsolePanel.clientHeight > 1, "The actual height of the console is bound with a min height"); @@ -63,6 +69,14 @@ function test() { yield toolbox.destroy(); } + function getActiveElement(doc) { + let activeElement = doc.activeElement; + while (activeElement && activeElement.contentDocument) { + activeElement = activeElement.contentDocument.activeElement; + } + return activeElement; + } + function getVisiblePrefValue() { return Services.prefs.getBoolPref("devtools.toolbox.splitconsoleEnabled"); } From 1bdffeaf7d6b952606389091080b86df9e47f1b7 Mon Sep 17 00:00:00 2001 From: Eric Edens Date: Thu, 14 Aug 2014 17:17:29 -0700 Subject: [PATCH 55/86] Bug 1048525 - Use SuggestClient from MC. r=margaret --HG-- rename : mobile/android/base/home/SuggestClient.java => mobile/android/base/SuggestClient.java --- .../base/{home => }/SuggestClient.java | 12 +- mobile/android/base/home/BrowserSearch.java | 1 + mobile/android/base/moz.build | 2 +- .../base/tests/testSearchSuggestions.java | 2 +- .../search/autocomplete/SuggestClient.java | 145 ------------------ .../autocomplete/SuggestionsFragment.java | 1 + .../search/search_activity_sources.mozbuild | 1 - 7 files changed, 13 insertions(+), 151 deletions(-) rename mobile/android/base/{home => }/SuggestClient.java (92%) delete mode 100644 mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java diff --git a/mobile/android/base/home/SuggestClient.java b/mobile/android/base/SuggestClient.java similarity index 92% rename from mobile/android/base/home/SuggestClient.java rename to mobile/android/base/SuggestClient.java index 7b3d41bd165c..98ce09a6042f 100644 --- a/mobile/android/base/home/SuggestClient.java +++ b/mobile/android/base/SuggestClient.java @@ -2,10 +2,12 @@ * 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/. */ -package org.mozilla.gecko.home; +package org.mozilla.gecko; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.mozglue.RobocopTarget; +import org.mozilla.gecko.util.HardwareUtils; import org.json.JSONArray; @@ -28,7 +30,11 @@ import java.util.ArrayList; */ public class SuggestClient { private static final String LOGTAG = "GeckoSuggestClient"; - private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString(); + + // This should go through GeckoInterface to get the UA, but the search activity + // doesn't use a GeckoView yet. Until it does, get the UA directly. + private static final String USER_AGENT = HardwareUtils.isTablet() ? + AppConstants.USER_AGENT_FENNEC_TABLET : AppConstants.USER_AGENT_FENNEC_MOBILE; private final Context mContext; private final int mTimeout; @@ -112,7 +118,7 @@ public class SuggestClient { */ JSONArray results = new JSONArray(json); JSONArray jsonSuggestions = results.getJSONArray(1); - + int added = 0; for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) { String suggestion = jsonSuggestions.getString(i); diff --git a/mobile/android/base/home/BrowserSearch.java b/mobile/android/base/home/BrowserSearch.java index 36531671c957..091c5c88cfe6 100644 --- a/mobile/android/base/home/BrowserSearch.java +++ b/mobile/android/base/home/BrowserSearch.java @@ -19,6 +19,7 @@ import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.R; +import org.mozilla.gecko.SuggestClient; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; import org.mozilla.gecko.Telemetry; diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index d9f43613a89a..0986d04c70fc 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -302,7 +302,6 @@ gbjar.sources += [ 'home/SearchEngineRow.java', 'home/SearchLoader.java', 'home/SimpleCursorLoader.java', - 'home/SuggestClient.java', 'home/TabMenuStrip.java', 'home/TabMenuStripLayout.java', 'home/TopSitesGridItemView.java', @@ -379,6 +378,7 @@ gbjar.sources += [ 'sqlite/MatrixBlobCursor.java', 'sqlite/SQLiteBridge.java', 'sqlite/SQLiteBridgeException.java', + 'SuggestClient.java', 'SurfaceBits.java', 'Tab.java', 'Tabs.java', diff --git a/mobile/android/base/tests/testSearchSuggestions.java b/mobile/android/base/tests/testSearchSuggestions.java index 48bc6fdd5dc7..8b3ea27426cf 100644 --- a/mobile/android/base/tests/testSearchSuggestions.java +++ b/mobile/android/base/tests/testSearchSuggestions.java @@ -5,8 +5,8 @@ import java.util.HashMap; import org.mozilla.gecko.Actions; import org.mozilla.gecko.R; +import org.mozilla.gecko.SuggestClient; import org.mozilla.gecko.home.BrowserSearch; -import org.mozilla.gecko.home.SuggestClient; import android.app.Activity; import android.support.v4.app.Fragment; diff --git a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java b/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java deleted file mode 100644 index bd66eefc1d54..000000000000 --- a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java +++ /dev/null @@ -1,145 +0,0 @@ -/* 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/. */ - -package org.mozilla.search.autocomplete; - -import org.json.JSONArray; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.text.TextUtils; -import android.util.Log; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; - -/** - * Use network-based search suggestions. - */ -public class SuggestClient { - private static final String LOGTAG = "GeckoSuggestClient"; - private static final String USER_AGENT = ""; - - private final Context mContext; - private final int mTimeout; - - // should contain the string "__searchTerms__", which is replaced with the query - private final String mSuggestTemplate; - - // the maximum number of suggestions to return - private final int mMaxResults; - - // used by robocop for testing - private boolean mCheckNetwork; - - // used to make suggestions appear instantly after opt-in - private String mPrevQuery; - private ArrayList mPrevResults; - - public SuggestClient(Context context, String suggestTemplate, int timeout, int maxResults) { - mContext = context; - mMaxResults = maxResults; - mSuggestTemplate = suggestTemplate; - mTimeout = timeout; - mCheckNetwork = true; - } - - /** - * Queries for a given search term and returns an ArrayList of suggestions. - */ - public ArrayList query(String query) { - if (query.equals(mPrevQuery)) - return mPrevResults; - - ArrayList suggestions = new ArrayList(); - if (TextUtils.isEmpty(mSuggestTemplate) || TextUtils.isEmpty(query)) { - return suggestions; - } - - if (!isNetworkConnected() && mCheckNetwork) { - Log.i(LOGTAG, "Not connected to network"); - return suggestions; - } - - try { - String encoded = URLEncoder.encode(query, "UTF-8"); - String suggestUri = mSuggestTemplate.replace("__searchTerms__", encoded); - - URL url = new URL(suggestUri); - String json = null; - HttpURLConnection urlConnection = null; - InputStream in = null; - try { - urlConnection = (HttpURLConnection) url.openConnection(); - urlConnection.setConnectTimeout(mTimeout); - urlConnection.setRequestProperty("User-Agent", USER_AGENT); - in = new BufferedInputStream(urlConnection.getInputStream()); - json = convertStreamToString(in); - } finally { - if (urlConnection != null) - urlConnection.disconnect(); - if (in != null) { - try { - in.close(); - } catch (IOException e) { - Log.e(LOGTAG, "error", e); - } - } - } - - if (json != null) { - /* - * Sample result: - * ["foo",["food network","foothill college","foot locker",...]] - */ - JSONArray results = new JSONArray(json); - JSONArray jsonSuggestions = results.getJSONArray(1); - - int added = 0; - for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) { - String suggestion = jsonSuggestions.getString(i); - if (!suggestion.equalsIgnoreCase(query)) { - suggestions.add(suggestion); - added++; - } - } - } else { - Log.e(LOGTAG, "Suggestion query failed"); - } - } catch (Exception e) { - Log.e(LOGTAG, "Error", e); - } - - mPrevQuery = query; - mPrevResults = suggestions; - return suggestions; - } - - private boolean isNetworkConnected() { - NetworkInfo networkInfo = getActiveNetworkInfo(); - return networkInfo != null && networkInfo.isConnected(); - } - - private NetworkInfo getActiveNetworkInfo() { - ConnectivityManager connectivity = (ConnectivityManager) mContext - .getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) - return null; - return connectivity.getActiveNetworkInfo(); - } - - private String convertStreamToString(java.io.InputStream is) { - try { - return new java.util.Scanner(is).useDelimiter("\\A").next(); - } catch (java.util.NoSuchElementException e) { - return ""; - } - } -} diff --git a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java b/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java index 466f4cc17f02..f7ce0a948f3a 100644 --- a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java +++ b/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java @@ -21,6 +21,7 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; +import org.mozilla.gecko.SuggestClient; import org.mozilla.gecko.Telemetry; import org.mozilla.gecko.TelemetryContract; import org.mozilla.search.AcceptsSearchQuery; diff --git a/mobile/android/search/search_activity_sources.mozbuild b/mobile/android/search/search_activity_sources.mozbuild index a9892ac05676..a533484ab7db 100644 --- a/mobile/android/search/search_activity_sources.mozbuild +++ b/mobile/android/search/search_activity_sources.mozbuild @@ -8,7 +8,6 @@ search_activity_sources = [ 'java/org/mozilla/search/AcceptsSearchQuery.java', 'java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java', 'java/org/mozilla/search/autocomplete/ClearableEditText.java', - 'java/org/mozilla/search/autocomplete/SuggestClient.java', 'java/org/mozilla/search/autocomplete/SuggestionsFragment.java', 'java/org/mozilla/search/Constants.java', 'java/org/mozilla/search/MainActivity.java', From 141477bfbd7148113185ca6050abac6f65ba0e0e Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Fri, 15 Aug 2014 10:42:37 -0400 Subject: [PATCH 56/86] Bug 1050447 - Skip focusing content if we're opening a new about:blank or about:newtab tab. r=Unfocused. This fixes a change in order of focus events for e10s after bug 1009628 landed. We were accidentally focusing the content after focusing the URL bar for new tabs. We now skip focusing the content entirely when opening a new tab. --HG-- extra : histedit_source : ce4239e776b58992ccec65d2ade578e68978240c%2Cb9bded035324f4bdc3e6533c1edffb8dc0107ff3 --- browser/base/content/utilityOverlay.js | 29 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 3dca6c5b0734..e8604e0ae1da 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -309,6 +309,8 @@ function openLinkIn(url, where, params) { // result in a new frontmost window (e.g. "javascript:window.open('');"). w.focus(); + let newTab; + switch (where) { case "current": let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; @@ -332,22 +334,29 @@ function openLinkIn(url, where, params) { // fall through case "tab": let browser = w.gBrowser; - browser.loadOneTab(url, { - referrerURI: aReferrerURI, - charset: aCharset, - postData: aPostData, - inBackground: loadInBackground, - allowThirdPartyFixup: aAllowThirdPartyFixup, - relatedToCurrent: aRelatedToCurrent, - skipAnimation: aSkipTabAnimation, - allowMixedContent: aAllowMixedContent }); + newTab = browser.loadOneTab(url, { + referrerURI: aReferrerURI, + charset: aCharset, + postData: aPostData, + inBackground: loadInBackground, + allowThirdPartyFixup: aAllowThirdPartyFixup, + relatedToCurrent: aRelatedToCurrent, + skipAnimation: aSkipTabAnimation, + allowMixedContent: aAllowMixedContent }); break; } w.gBrowser.selectedBrowser.focus(); - if (!loadInBackground && w.isBlankPageURL(url)) + if (!loadInBackground && w.isBlankPageURL(url)) { + if (newTab) { + // Remote tab content does not focus synchronously, so we set the flag + // on this tab to skip focusing the content if we want to focus the URL + // bar instead. + newTab._urlbarFocused = true; + } w.focusAndSelectUrlBar(); + } } // Used as an onclick handler for UI elements with link-like behavior. From cbcdd8a7968d93052790e183b774e4cac8f635c1 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Fri, 15 Aug 2014 16:21:41 +0100 Subject: [PATCH 57/86] Backed out changeset ad5e5e0f18ea (bug 1026561) for intermittent test failures --- browser/app/profile/firefox.js | 2 +- .../base/content/test/newtab/browser_newtab_bug752841.js | 4 ++-- .../content/test/newtab/browser_newtab_drag_drop_ext.js | 7 +------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 3b5227456fc7..522b708f72aa 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1522,7 +1522,7 @@ pref("browser.newtabpage.enhanced", false); pref("browser.newtabpage.rows", 3); // number of columns of newtab grid -pref("browser.newtabpage.columns", 8); +pref("browser.newtabpage.columns", 3); // directory tiles download URL pref("browser.newtabpage.directory.source", "chrome://global/content/directoryLinks.json"); diff --git a/browser/base/content/test/newtab/browser_newtab_bug752841.js b/browser/base/content/test/newtab/browser_newtab_bug752841.js index c19272417cae..91c347b0c8d6 100644 --- a/browser/base/content/test/newtab/browser_newtab_bug752841.js +++ b/browser/base/content/test/newtab/browser_newtab_bug752841.js @@ -17,8 +17,8 @@ function runTests() { // Expected length of grid let expectedValues = [1, 1, 1, 1, 8, 10]; - // Values before setting new pref values (24 is the default value -> 8 x 3) - let previousValues = [24, 1, 1, 1, 1, 8]; + // Values before setting new pref values (9 is the default value -> 3 x 3) + let previousValues = [9, 1, 1, 1, 1, 8]; let existingTab, existingTabGridLength, newTab, newTabGridLength; yield addNewTabPageTab(); diff --git a/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js b/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js index 11dc4dfda2ab..1ba7cfed8be2 100644 --- a/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js +++ b/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js @@ -1,8 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns"; - /* * These tests make sure that dragging and dropping sites works as expected. * Sites contained in the grid need to shift around to indicate the result @@ -30,11 +28,8 @@ function runTests() { yield addNewTabPageTab(); checkGrid("0,1,2,3,4,5,6,7p,8p"); - // force the grid to be small enough that a pinned cell could be pushed out - Services.prefs.setIntPref(PREF_NEWTAB_COLUMNS, 3); yield simulateExternalDrop(7); checkGrid("0,1,2,3,4,5,7p,99p,8p"); - Services.prefs.clearUserPref(PREF_NEWTAB_COLUMNS); // drag a new site beneath a pinned cell and make sure the pinned cell is // not moved @@ -57,4 +52,4 @@ function runTests() { yield simulateExternalDrop(1); checkGrid("0p,99p,1p,2p,3,4,5,6,7"); -} +} \ No newline at end of file From 2864da5d9efd8a246860b449c94d9fa593fd3381 Mon Sep 17 00:00:00 2001 From: Richard Marti Date: Tue, 12 Aug 2014 20:54:40 +0200 Subject: [PATCH 58/86] Bug 989469 - Move the common files from browser to global. r=Unfocused --HG-- rename : browser/themes/linux/in-content/common.css => toolkit/themes/linux/global/in-content/common.css rename : browser/themes/osx/in-content/common.css => toolkit/themes/osx/global/in-content/common.css rename : browser/themes/shared/in-content/check.png => toolkit/themes/shared/in-content/check.png rename : browser/themes/shared/in-content/check@2x.png => toolkit/themes/shared/in-content/check@2x.png rename : browser/themes/shared/in-content/common.inc.css => toolkit/themes/shared/in-content/common.inc.css rename : browser/themes/shared/in-content/dropdown-disabled.png => toolkit/themes/shared/in-content/dropdown-disabled.png rename : browser/themes/shared/in-content/dropdown-disabled@2x.png => toolkit/themes/shared/in-content/dropdown-disabled@2x.png rename : browser/themes/shared/in-content/dropdown.png => toolkit/themes/shared/in-content/dropdown.png rename : browser/themes/shared/in-content/dropdown@2x.png => toolkit/themes/shared/in-content/dropdown@2x.png rename : browser/themes/shared/in-content/help-glyph.png => toolkit/themes/shared/in-content/help-glyph.png rename : browser/themes/shared/in-content/help-glyph@2x.png => toolkit/themes/shared/in-content/help-glyph@2x.png rename : browser/themes/shared/in-content/sorter.png => toolkit/themes/shared/in-content/sorter.png rename : browser/themes/shared/in-content/sorter@2x.png => toolkit/themes/shared/in-content/sorter@2x.png rename : browser/themes/windows/in-content/common.css => toolkit/themes/windows/global/in-content/common.css --- .../base/content/aboutneterror/netError.css | 2 +- .../preferences/in-content/preferences.xul | 2 +- .../preferences/in-content/subdialogs.js | 2 +- browser/themes/linux/jar.mn | 11 --------- browser/themes/osx/jar.mn | 11 --------- .../shared/incontentprefs/preferences.css | 4 ++-- browser/themes/windows/jar.mn | 22 ------------------ .../linux/global}/in-content/common.css | 2 +- toolkit/themes/linux/global/jar.mn | 11 +++++++++ .../themes/osx/global}/in-content/common.css | 2 +- toolkit/themes/osx/global/jar.mn | 11 +++++++++ .../themes/shared/in-content/check.png | Bin .../themes/shared/in-content/check@2x.png | Bin .../themes/shared/in-content/common.inc.css | 18 +++++++------- .../shared/in-content/dropdown-disabled.png | Bin .../in-content/dropdown-disabled@2x.png | Bin .../themes/shared/in-content/dropdown.png | Bin .../themes/shared/in-content/dropdown@2x.png | Bin .../themes/shared/in-content/help-glyph.png | Bin .../shared/in-content/help-glyph@2x.png | Bin .../themes/shared/in-content/sorter.png | Bin .../themes/shared/in-content/sorter@2x.png | Bin .../windows/global}/in-content/common.css | 2 +- toolkit/themes/windows/global/jar.mn | 22 ++++++++++++++++++ 24 files changed, 61 insertions(+), 61 deletions(-) rename {browser/themes/linux => toolkit/themes/linux/global}/in-content/common.css (96%) rename {browser/themes/osx => toolkit/themes/osx/global}/in-content/common.css (96%) rename {browser => toolkit}/themes/shared/in-content/check.png (100%) rename {browser => toolkit}/themes/shared/in-content/check@2x.png (100%) rename {browser => toolkit}/themes/shared/in-content/common.inc.css (94%) rename {browser => toolkit}/themes/shared/in-content/dropdown-disabled.png (100%) rename {browser => toolkit}/themes/shared/in-content/dropdown-disabled@2x.png (100%) rename {browser => toolkit}/themes/shared/in-content/dropdown.png (100%) rename {browser => toolkit}/themes/shared/in-content/dropdown@2x.png (100%) rename {browser => toolkit}/themes/shared/in-content/help-glyph.png (100%) rename {browser => toolkit}/themes/shared/in-content/help-glyph@2x.png (100%) rename {browser => toolkit}/themes/shared/in-content/sorter.png (100%) rename {browser => toolkit}/themes/shared/in-content/sorter@2x.png (100%) rename {browser/themes/windows => toolkit/themes/windows/global}/in-content/common.css (93%) diff --git a/browser/base/content/aboutneterror/netError.css b/browser/base/content/aboutneterror/netError.css index e4c6d6c7041a..14b206b99547 100644 --- a/browser/base/content/aboutneterror/netError.css +++ b/browser/base/content/aboutneterror/netError.css @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -@import url("chrome://browser/skin/in-content/common.css"); +@import url("chrome://global/skin/in-content/common.css"); body { display: flex; diff --git a/browser/components/preferences/in-content/preferences.xul b/browser/components/preferences/in-content/preferences.xul index 1fb30c17d9c5..c2b0330d53c2 100644 --- a/browser/components/preferences/in-content/preferences.xul +++ b/browser/components/preferences/in-content/preferences.xul @@ -8,7 +8,7 @@ - + .treecol-sortdirection[sortDirection=descending], #actionColumn > .treecol-sortdirection[sortDirection=descending] { -moz-appearance: none; - list-style-image: url("chrome://browser/skin/in-content/sorter.png"); + list-style-image: url("chrome://global/skin/in-content/sorter.png"); } #typeColumn > .treecol-sortdirection[sortDirection=descending], @@ -182,7 +182,7 @@ prefpane { #actionColumn > .treecol-sortdirection[sortDirection=descending] { width: 12px; height: 8px; - list-style-image: url("chrome://browser/skin/in-content/sorter@2x.png"); + list-style-image: url("chrome://global/skin/in-content/sorter@2x.png"); } } diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index 29bb0520beed..2ebf5f93d156 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -37,17 +37,6 @@ browser.jar: skin/classic/browser/identity-icons-https-ev.png skin/classic/browser/identity-icons-https-mixed-active.png skin/classic/browser/identity-icons-https-mixed-display.png -* skin/classic/browser/in-content/common.css (in-content/common.css) - skin/classic/browser/in-content/check.png (../shared/in-content/check.png) - skin/classic/browser/in-content/check@2x.png (../shared/in-content/check@2x.png) - skin/classic/browser/in-content/dropdown.png (../shared/in-content/dropdown.png) - skin/classic/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png) - skin/classic/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png) - skin/classic/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png) - skin/classic/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png) - skin/classic/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png) - skin/classic/browser/in-content/sorter.png (../shared/in-content/sorter.png) - skin/classic/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png) skin/classic/browser/keyhole-forward-mask.svg skin/classic/browser/KUI-background.png skin/classic/browser/livemark-folder.png @@ -457,17 +446,6 @@ browser.jar: skin/classic/aero/browser/identity-icons-https-ev.png skin/classic/aero/browser/identity-icons-https-mixed-active.png skin/classic/aero/browser/identity-icons-https-mixed-display.png -* skin/classic/aero/browser/in-content/common.css (in-content/common.css) - skin/classic/aero/browser/in-content/check.png (../shared/in-content/check.png) - skin/classic/aero/browser/in-content/check@2x.png (../shared/in-content/check@2x.png) - skin/classic/aero/browser/in-content/dropdown.png (../shared/in-content/dropdown.png) - skin/classic/aero/browser/in-content/dropdown@2x.png (../shared/in-content/dropdown@2x.png) - skin/classic/aero/browser/in-content/dropdown-disabled.png (../shared/in-content/dropdown-disabled.png) - skin/classic/aero/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png) - skin/classic/aero/browser/in-content/help-glyph.png (../shared/in-content/help-glyph.png) - skin/classic/aero/browser/in-content/help-glyph@2x.png (../shared/in-content/help-glyph@2x.png) - skin/classic/aero/browser/in-content/sorter.png (../shared/in-content/sorter.png) - skin/classic/aero/browser/in-content/sorter@2x.png (../shared/in-content/sorter@2x.png) skin/classic/aero/browser/keyhole-forward-mask.svg skin/classic/aero/browser/KUI-background.png skin/classic/aero/browser/livemark-folder.png (livemark-folder-aero.png) diff --git a/browser/themes/linux/in-content/common.css b/toolkit/themes/linux/global/in-content/common.css similarity index 96% rename from browser/themes/linux/in-content/common.css rename to toolkit/themes/linux/global/in-content/common.css index f1a1c7b1a956..ca3635fb91e6 100644 --- a/browser/themes/linux/in-content/common.css +++ b/toolkit/themes/linux/global/in-content/common.css @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this file, - You can obtain one at http://mozilla.org/MPL/2.0/. */ -%include ../../shared/in-content/common.inc.css +%include ../../../shared/in-content/common.inc.css xul|tab[selected] { /* Override styles for tab[selected] from diff --git a/toolkit/themes/linux/global/jar.mn b/toolkit/themes/linux/global/jar.mn index b0c9d32e5671..b20d4aa2e907 100644 --- a/toolkit/themes/linux/global/jar.mn +++ b/toolkit/themes/linux/global/jar.mn @@ -54,4 +54,15 @@ toolkit.jar: + skin/classic/global/icons/webapps-16.png (icons/webapps-16.png) + skin/classic/global/icons/webapps-64.png (icons/webapps-64.png) skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png) +* skin/classic/global/in-content/common.css (in-content/common.css) + skin/classic/global/in-content/check.png (../../shared/in-content/check.png) + skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png) + skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png) + skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png) + skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png) + skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png) + skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png) + skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png) + skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png) + skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png) + skin/classic/global/toolbar/spring.png (toolbar/spring.png) diff --git a/browser/themes/osx/in-content/common.css b/toolkit/themes/osx/global/in-content/common.css similarity index 96% rename from browser/themes/osx/in-content/common.css rename to toolkit/themes/osx/global/in-content/common.css index 245edd755c7a..56406307e9ad 100644 --- a/browser/themes/osx/in-content/common.css +++ b/toolkit/themes/osx/global/in-content/common.css @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this file, - You can obtain one at http://mozilla.org/MPL/2.0/. */ -%include ../../shared/in-content/common.inc.css +%include ../../../shared/in-content/common.inc.css xul|tabs { padding-right: 0; diff --git a/toolkit/themes/osx/global/jar.mn b/toolkit/themes/osx/global/jar.mn index ebe54c0aea26..3bb1b59e87dd 100644 --- a/toolkit/themes/osx/global/jar.mn +++ b/toolkit/themes/osx/global/jar.mn @@ -184,6 +184,17 @@ toolkit.jar: skin/classic/global/menu/menu-arrow@2x.png (menu/menu-arrow@2x.png) skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png) skin/classic/global/menu/shared-menu-check@2x.png (../../shared/menu-check@2x.png) +* skin/classic/global/in-content/common.css (in-content/common.css) + skin/classic/global/in-content/check.png (../../shared/in-content/check.png) + skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png) + skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png) + skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png) + skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png) + skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png) + skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png) + skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png) + skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png) + skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png) skin/classic/global/scale/scale-tray-horiz.gif (scale/scale-tray-horiz.gif) skin/classic/global/scale/scale-tray-vert.gif (scale/scale-tray-vert.gif) skin/classic/global/splitter/dimple.png (splitter/dimple.png) diff --git a/browser/themes/shared/in-content/check.png b/toolkit/themes/shared/in-content/check.png similarity index 100% rename from browser/themes/shared/in-content/check.png rename to toolkit/themes/shared/in-content/check.png diff --git a/browser/themes/shared/in-content/check@2x.png b/toolkit/themes/shared/in-content/check@2x.png similarity index 100% rename from browser/themes/shared/in-content/check@2x.png rename to toolkit/themes/shared/in-content/check@2x.png diff --git a/browser/themes/shared/in-content/common.inc.css b/toolkit/themes/shared/in-content/common.inc.css similarity index 94% rename from browser/themes/shared/in-content/common.inc.css rename to toolkit/themes/shared/in-content/common.inc.css index 6fafd74988b8..2f16d677cb7b 100644 --- a/browser/themes/shared/in-content/common.inc.css +++ b/toolkit/themes/shared/in-content/common.inc.css @@ -194,7 +194,7 @@ xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker { height: 16px; border: none; background-color: transparent; - list-style-image: url("chrome://browser/skin/in-content/dropdown.png"); + list-style-image: url("chrome://global/skin/in-content/dropdown.png"); } xul|*.help-button { @@ -227,14 +227,14 @@ xul|*.help-button > xul|*.button-box { xul|*.help-button > xul|*.button-box > xul|*.button-icon { width: 26px; height: 26px; - background-image: url("chrome://browser/skin/in-content/help-glyph.png"); + background-image: url("chrome://global/skin/in-content/help-glyph.png"); background-position: center; } @media (min-resolution: 2dppx) { xul|*.help-button > xul|*.button-box > xul|*.button-icon { background-size: 26px 26px; - background-image: url("chrome://browser/skin/in-content/help-glyph@2x.png"); + background-image: url("chrome://global/skin/in-content/help-glyph@2x.png"); } } @@ -283,21 +283,21 @@ xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker { padding: 0; border: none; background-color: transparent; - list-style-image: url("chrome://browser/skin/in-content/dropdown.png"); + list-style-image: url("chrome://global/skin/in-content/dropdown.png"); } xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker { - list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled.png") + list-style-image: url("chrome://global/skin/in-content/dropdown-disabled.png") } @media (min-resolution: 2dppx) { xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker, xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker { - list-style-image: url("chrome://browser/skin/in-content/dropdown@2x.png"); + list-style-image: url("chrome://global/skin/in-content/dropdown@2x.png"); } xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker { - list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled@2x.png") + list-style-image: url("chrome://global/skin/in-content/dropdown-disabled@2x.png") } xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker > xul|*.dropmarker-icon, @@ -431,7 +431,7 @@ xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check { } xul|*.checkbox-check[checked] { - background-image: url("chrome://browser/skin/in-content/check.png"), + background-image: url("chrome://global/skin/in-content/check.png"), /* !important needed to override toolkit !important rule */ linear-gradient(#fff, rgba(255,255,255,0.8)) !important; } @@ -448,7 +448,7 @@ xul|*.checkbox-label-box { @media (min-resolution: 2dppx) { xul|*.checkbox-check[checked] { background-size: 12px 12px, auto; - background-image: url("chrome://browser/skin/in-content/check@2x.png"), + background-image: url("chrome://global/skin/in-content/check@2x.png"), linear-gradient(#fff, rgba(255,255,255,0.8)) !important; } } diff --git a/browser/themes/shared/in-content/dropdown-disabled.png b/toolkit/themes/shared/in-content/dropdown-disabled.png similarity index 100% rename from browser/themes/shared/in-content/dropdown-disabled.png rename to toolkit/themes/shared/in-content/dropdown-disabled.png diff --git a/browser/themes/shared/in-content/dropdown-disabled@2x.png b/toolkit/themes/shared/in-content/dropdown-disabled@2x.png similarity index 100% rename from browser/themes/shared/in-content/dropdown-disabled@2x.png rename to toolkit/themes/shared/in-content/dropdown-disabled@2x.png diff --git a/browser/themes/shared/in-content/dropdown.png b/toolkit/themes/shared/in-content/dropdown.png similarity index 100% rename from browser/themes/shared/in-content/dropdown.png rename to toolkit/themes/shared/in-content/dropdown.png diff --git a/browser/themes/shared/in-content/dropdown@2x.png b/toolkit/themes/shared/in-content/dropdown@2x.png similarity index 100% rename from browser/themes/shared/in-content/dropdown@2x.png rename to toolkit/themes/shared/in-content/dropdown@2x.png diff --git a/browser/themes/shared/in-content/help-glyph.png b/toolkit/themes/shared/in-content/help-glyph.png similarity index 100% rename from browser/themes/shared/in-content/help-glyph.png rename to toolkit/themes/shared/in-content/help-glyph.png diff --git a/browser/themes/shared/in-content/help-glyph@2x.png b/toolkit/themes/shared/in-content/help-glyph@2x.png similarity index 100% rename from browser/themes/shared/in-content/help-glyph@2x.png rename to toolkit/themes/shared/in-content/help-glyph@2x.png diff --git a/browser/themes/shared/in-content/sorter.png b/toolkit/themes/shared/in-content/sorter.png similarity index 100% rename from browser/themes/shared/in-content/sorter.png rename to toolkit/themes/shared/in-content/sorter.png diff --git a/browser/themes/shared/in-content/sorter@2x.png b/toolkit/themes/shared/in-content/sorter@2x.png similarity index 100% rename from browser/themes/shared/in-content/sorter@2x.png rename to toolkit/themes/shared/in-content/sorter@2x.png diff --git a/browser/themes/windows/in-content/common.css b/toolkit/themes/windows/global/in-content/common.css similarity index 93% rename from browser/themes/windows/in-content/common.css rename to toolkit/themes/windows/global/in-content/common.css index 2970a8e3a5da..75287a329f38 100644 --- a/browser/themes/windows/in-content/common.css +++ b/toolkit/themes/windows/global/in-content/common.css @@ -2,7 +2,7 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this file, - You can obtain one at http://mozilla.org/MPL/2.0/. */ -%include ../../shared/in-content/common.inc.css +%include ../../../shared/in-content/common.inc.css xul|caption { background-color: transparent; diff --git a/toolkit/themes/windows/global/jar.mn b/toolkit/themes/windows/global/jar.mn index 7b54126ed0ea..47fc203f9002 100644 --- a/toolkit/themes/windows/global/jar.mn +++ b/toolkit/themes/windows/global/jar.mn @@ -169,6 +169,17 @@ toolkit.jar: skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png) skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg) skin/classic/global/menu/shared-menu-check.png (../../shared/menu-check.png) +* skin/classic/global/in-content/common.css (in-content/common.css) + skin/classic/global/in-content/check.png (../../shared/in-content/check.png) + skin/classic/global/in-content/check@2x.png (../../shared/in-content/check@2x.png) + skin/classic/global/in-content/dropdown.png (../../shared/in-content/dropdown.png) + skin/classic/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png) + skin/classic/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png) + skin/classic/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png) + skin/classic/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png) + skin/classic/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png) + skin/classic/global/in-content/sorter.png (../../shared/in-content/sorter.png) + skin/classic/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png) skin/classic/global/printpreview/arrow-left.png (printpreview/arrow-left.png) skin/classic/global/printpreview/arrow-left-end.png (printpreview/arrow-left-end.png) skin/classic/global/printpreview/arrow-right.png (printpreview/arrow-right.png) @@ -352,6 +363,17 @@ toolkit.jar: skin/classic/aero/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png) skin/classic/aero/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg) skin/classic/aero/global/menu/shared-menu-check.png (../../shared/menu-check.png) +* skin/classic/aero/global/in-content/common.css (in-content/common.css) + skin/classic/aero/global/in-content/check.png (../../shared/in-content/check.png) + skin/classic/aero/global/in-content/check@2x.png (../../shared/in-content/check@2x.png) + skin/classic/aero/global/in-content/dropdown.png (../../shared/in-content/dropdown.png) + skin/classic/aero/global/in-content/dropdown@2x.png (../../shared/in-content/dropdown@2x.png) + skin/classic/aero/global/in-content/dropdown-disabled.png (../../shared/in-content/dropdown-disabled.png) + skin/classic/aero/global/in-content/dropdown-disabled@2x.png (../../shared/in-content/dropdown-disabled@2x.png) + skin/classic/aero/global/in-content/help-glyph.png (../../shared/in-content/help-glyph.png) + skin/classic/aero/global/in-content/help-glyph@2x.png (../../shared/in-content/help-glyph@2x.png) + skin/classic/aero/global/in-content/sorter.png (../../shared/in-content/sorter.png) + skin/classic/aero/global/in-content/sorter@2x.png (../../shared/in-content/sorter@2x.png) skin/classic/aero/global/printpreview/arrow-left.png (printpreview/arrow-left-aero.png) skin/classic/aero/global/printpreview/arrow-left-end.png (printpreview/arrow-left-end-aero.png) skin/classic/aero/global/printpreview/arrow-right.png (printpreview/arrow-right-aero.png) From 76038430e7fc1ecccf250d72201eb0facb694545 Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Thu, 14 Aug 2014 11:59:00 -0400 Subject: [PATCH 59/86] Bug 1003053 - Fix panel subview anchor arrow position. r=Gijs --- browser/themes/shared/customizableui/panelUIOverlay.inc.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/themes/shared/customizableui/panelUIOverlay.inc.css b/browser/themes/shared/customizableui/panelUIOverlay.inc.css index c1ec42995692..357311e85592 100644 --- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css +++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css @@ -897,14 +897,14 @@ toolbarbutton[panel-multiview-anchor="true"] > .toolbarbutton-menubutton-button toolbarbutton[panel-multiview-anchor="true"] { background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted.png), linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0)); - background-position: right 5px center; + background-position: right calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center; background-repeat: no-repeat, repeat; } toolbarbutton[panel-multiview-anchor="true"]:-moz-locale-dir(rtl) { background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png), linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0)); - background-position: left 5px center; + background-position: left calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center; } toolbarpaletteitem[place="palette"] > .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker, From 058fbc6a514d286222a802c3daac7151162671b7 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 13 Aug 2014 15:10:00 -0400 Subject: [PATCH 60/86] Bug 1007059 - Enable WebIDE by default. r=paul --- browser/app/profile/firefox.js | 4 ++-- .../devtools/framework/test/browser_dynamic_tool_enabling.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 522b708f72aa..c394dbec613a 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1280,8 +1280,8 @@ pref("devtools.appmanager.enabled", true); pref("devtools.appmanager.lastTab", "help"); pref("devtools.appmanager.manifestEditor.enabled", true); -// Disable devtools webide until bug 1007059 -pref("devtools.webide.enabled", false); +// Enable DevTools WebIDE by default +pref("devtools.webide.enabled", true); // Toolbox preferences pref("devtools.toolbox.footer.height", 250); diff --git a/browser/devtools/framework/test/browser_dynamic_tool_enabling.js b/browser/devtools/framework/test/browser_dynamic_tool_enabling.js index e09becaeb9d7..54ebd5ede1f4 100644 --- a/browser/devtools/framework/test/browser_dynamic_tool_enabling.js +++ b/browser/devtools/framework/test/browser_dynamic_tool_enabling.js @@ -5,7 +5,6 @@ let gItemsToTest = { "menu_devToolbar": "devtools.toolbar.enabled", - "menu_devAppMgr": "devtools.appmanager.enabled", "menu_browserToolbox": ["devtools.chrome.enabled", "devtools.debugger.remote-enabled", "devtools.debugger.chrome-enabled"], "javascriptConsole": "devtools.errorconsole.enabled", "menu_devtools_connect": "devtools.debugger.remote-enabled", From 2da863c76521505c3b170747adf797244791abcd Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Thu, 14 Aug 2014 18:20:00 -0400 Subject: [PATCH 61/86] Bug 1007642 - Remove pointer cursor for Location Bar and search buttons on Linux. r=Gijs --- browser/themes/linux/browser.css | 2 -- browser/themes/linux/searchbar.css | 1 - 2 files changed, 3 deletions(-) diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css index f72a827b8950..d3561d76e0d4 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -881,7 +881,6 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon { } .urlbar-icon { - cursor: pointer; padding: 0 3px; } @@ -1524,7 +1523,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- #urlbar > toolbarbutton { -moz-appearance: none; padding: 0 2px; - cursor: pointer; list-style-image: url("chrome://browser/skin/reload-stop-go.png"); } diff --git a/browser/themes/linux/searchbar.css b/browser/themes/linux/searchbar.css index 4bf92317bb74..78462bdb6c15 100644 --- a/browser/themes/linux/searchbar.css +++ b/browser/themes/linux/searchbar.css @@ -57,7 +57,6 @@ .search-go-button { padding: 1px; list-style-image: url(moz-icon://stock/gtk-find?size=menu); - cursor: pointer; } menuitem[cmd="cmd_clearhistory"] { From 1882ac614148f1577d8ef21ef28591edcbcbd0eb Mon Sep 17 00:00:00 2001 From: Jordan Santell Date: Thu, 14 Aug 2014 11:57:00 -0400 Subject: [PATCH 62/86] Bug 1016037 - Remove actor IDs from web audio editor's inspector. r=vp --- .../webaudioeditor/test/browser_wa_inspector-toggle.js | 2 +- browser/devtools/webaudioeditor/test/browser_wa_inspector.js | 4 ++-- browser/devtools/webaudioeditor/webaudioeditor-view.js | 2 +- browser/themes/shared/devtools/webaudioeditor.inc.css | 4 ++++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js b/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js index 8fe636b08caf..64f49b0b3799 100644 --- a/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js +++ b/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js @@ -58,7 +58,7 @@ function spawnTest() { "Empty message hides even when loading node while open."); ok(isVisible($("#web-audio-editor-tabs")), "Switches to tab view when loading node while open."); - is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")", + is($("#web-audio-inspector-title").value, "Oscillator", "Inspector title updates when loading node while open."); yield teardown(panel); diff --git a/browser/devtools/webaudioeditor/test/browser_wa_inspector.js b/browser/devtools/webaudioeditor/test/browser_wa_inspector.js index b8e21474d6e1..1db3f44ed4d5 100644 --- a/browser/devtools/webaudioeditor/test/browser_wa_inspector.js +++ b/browser/devtools/webaudioeditor/test/browser_wa_inspector.js @@ -43,7 +43,7 @@ function spawnTest() { ok(isVisible($("#web-audio-editor-tabs")), "InspectorView tabs view visible when node selected."); - is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")", + is($("#web-audio-inspector-title").value, "Oscillator", "Inspector should have the node title when a node is selected."); is($("#web-audio-editor-tabs").selectedIndex, 0, @@ -52,7 +52,7 @@ function spawnTest() { click(panelWin, findGraphNode(panelWin, nodeIds[2])); yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET); - is($("#web-audio-inspector-title").value, "GainNode (" + nodeIds[2] + ")", + is($("#web-audio-inspector-title").value, "Gain", "Inspector title updates when a new node is selected."); yield teardown(panel); diff --git a/browser/devtools/webaudioeditor/webaudioeditor-view.js b/browser/devtools/webaudioeditor/webaudioeditor-view.js index 124defe1fb7c..4fbe8d8eac48 100644 --- a/browser/devtools/webaudioeditor/webaudioeditor-view.js +++ b/browser/devtools/webaudioeditor/webaudioeditor-view.js @@ -452,7 +452,7 @@ let WebAudioInspectorView = { */ _setTitle: function () { let node = this._currentNode; - let title = node.type + " (" + node.id + ")"; + let title = node.type.replace(/Node$/, ""); $("#web-audio-inspector-title").setAttribute("value", title); }, diff --git a/browser/themes/shared/devtools/webaudioeditor.inc.css b/browser/themes/shared/devtools/webaudioeditor.inc.css index 887bfdcaef1a..4d2665edf744 100644 --- a/browser/themes/shared/devtools/webaudioeditor.inc.css +++ b/browser/themes/shared/devtools/webaudioeditor.inc.css @@ -99,6 +99,10 @@ text { * Inspector Styles */ +#web-audio-inspector-title { + margin: 6px; +} + .web-audio-inspector .error { background-image: url(alerticon-warning.png); background-size: 13px 12px; From 74490c15d40ad797592b5c510eb65755a22977dd Mon Sep 17 00:00:00 2001 From: Ethan Pransky Date: Wed, 13 Aug 2014 10:39:32 -0700 Subject: [PATCH 63/86] Bug 1016613 - Replace RemoteTabsPanel view with ViewStub in tabs_panel.xml and create new layout file to inflate the ViewStub when user clicks on 3rd button in TabsPanel. r=mcomella This was done in order to save on resources and not create the RemoteTabsPanel until needed --- .../layout-large-land-v11/tabs_panel.xml | 9 ++-- .../layout/remote_tabs_panel_view.xml | 9 ++++ .../base/resources/layout/tabs_panel.xml | 9 ++-- mobile/android/base/tabs/TabsPanel.java | 41 ++++++++++++++++--- 4 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 mobile/android/base/resources/layout/remote_tabs_panel_view.xml diff --git a/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml b/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml index 80f34c2f6ae9..e0957278ef2e 100644 --- a/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml +++ b/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml @@ -46,11 +46,10 @@ android:layout_height="match_parent" android:visibility="gone"/> - + diff --git a/mobile/android/base/resources/layout/remote_tabs_panel_view.xml b/mobile/android/base/resources/layout/remote_tabs_panel_view.xml new file mode 100644 index 000000000000..aacb7b6df07c --- /dev/null +++ b/mobile/android/base/resources/layout/remote_tabs_panel_view.xml @@ -0,0 +1,9 @@ + + + + diff --git a/mobile/android/base/resources/layout/tabs_panel.xml b/mobile/android/base/resources/layout/tabs_panel.xml index 4a481c0f367e..68e5a655bb51 100644 --- a/mobile/android/base/resources/layout/tabs_panel.xml +++ b/mobile/android/base/resources/layout/tabs_panel.xml @@ -45,11 +45,10 @@ android:layout_height="match_parent" android:visibility="gone"/> - + diff --git a/mobile/android/base/tabs/TabsPanel.java b/mobile/android/base/tabs/TabsPanel.java index 33fa3860b545..612ae83f3d31 100644 --- a/mobile/android/base/tabs/TabsPanel.java +++ b/mobile/android/base/tabs/TabsPanel.java @@ -32,6 +32,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewStub; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageButton; @@ -113,7 +114,7 @@ public class TabsPanel extends LinearLayout public void onResume() { if (mPanel == mPanelRemote) { // Refresh the remote panel. - mPanelRemote.show(); + getRemotePanelView().show(); } } @@ -127,7 +128,23 @@ public class TabsPanel extends LinearLayout }; } + /** + * Initializes views in tabs_panel layout + * + * @throws IllegalStateException + * mCurrentPanel must have a non-null value + */ private void initialize() { + if (mCurrentPanel == null) { + throw new IllegalStateException( + "mCurrentPanel cannot be null in order for RemotePanelView to be initialized"); + } + + if (mCurrentPanel == Panel.REMOTE_TABS) { + // Initializes mPanelRemote + getRemotePanelView(); + } + mHeader = (RelativeLayout) findViewById(R.id.tabs_panel_header); mTabsContainer = (TabsListContainer) findViewById(R.id.tabs_container); @@ -137,9 +154,6 @@ public class TabsPanel extends LinearLayout mPanelPrivate = (PanelView) findViewById(R.id.private_tabs_panel); mPanelPrivate.setTabsPanel(this); - mPanelRemote = (PanelView) findViewById(R.id.remote_tabs); - mPanelRemote.setTabsPanel(this); - mFooter = (RelativeLayout) findViewById(R.id.tabs_panel_footer); mAddTab = (ImageButton) findViewById(R.id.add_tab); @@ -416,7 +430,7 @@ public class TabsPanel extends LinearLayout mPanel = mPanelPrivate; break; case REMOTE_TABS: - mPanel = mPanelRemote; + mPanel = getRemotePanelView(); break; default: @@ -472,6 +486,9 @@ public class TabsPanel extends LinearLayout public void refresh() { removeAllViews(); + // The View that mPanelRemote points to is invalidated because the layout is invalidated. + // mPanelRemote must be null in order to properly initialize RemotePanelView. + mPanelRemote = null; LayoutInflater.from(mContext).inflate(R.layout.tabs_panel, this); initialize(); @@ -570,4 +587,18 @@ public class TabsPanel extends LinearLayout public void setIconDrawable(Panel panel, int resource) { mTabWidget.setIconDrawable(panel.ordinal(), resource); } + + /** + * Initializes mPanelRemote if necessary and provides getter because you + * should probably not access mPanelRemote directly + * + * @return PanelView + */ + private PanelView getRemotePanelView() { + if (mPanelRemote == null) { + mPanelRemote = (PanelView) ((ViewStub) findViewById(R.id.remote_tabs_panel_stub)).inflate(); + mPanelRemote.setTabsPanel(TabsPanel.this); + } + return mPanelRemote; + } } From a442e0403a061e04ebc0b672174a8ea0c15cdaf3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 14 Aug 2014 07:03:00 -0400 Subject: [PATCH 64/86] Bug 1028903 - Improve self-xss warning message for Scratchpad. r=jwalker --- browser/devtools/scratchpad/scratchpad.js | 5 ++++- browser/devtools/webconsole/webconsole.js | 6 +++++- .../chrome/browser/devtools/scratchpad.properties | 10 ++++++++++ toolkit/devtools/webconsole/utils.js | 6 ++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/browser/devtools/scratchpad/scratchpad.js b/browser/devtools/scratchpad/scratchpad.js index 3fd7654ecc69..59f21dead8ce 100644 --- a/browser/devtools/scratchpad/scratchpad.js +++ b/browser/devtools/scratchpad/scratchpad.js @@ -1614,8 +1614,11 @@ var Scratchpad = { var lines = initialText.split("\n"); this.editor.on("change", this._onChanged); + let okstring = this.strings.GetStringFromName("selfxss.okstring"); + let msg = this.strings.formatStringFromName("selfxss.msg", [okstring], 1); this._onPaste = WebConsoleUtils.pasteHandlerGen(this.editor.container.contentDocument.body, - document.querySelector('#scratchpad-notificationbox')); + document.querySelector('#scratchpad-notificationbox'), + msg, okstring); editorElement.addEventListener("paste", this._onPaste); editorElement.addEventListener("drop", this._onPaste); this.editor.on("save", () => this.saveFile()); diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 89107707e077..611231d32b93 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -3137,7 +3137,11 @@ JSTerm.prototype = { inputContainer.style.display = "none"; } else { - this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode, doc.getElementById("webconsole-notificationbox")); + let okstring = l10n.getStr("selfxss.okstring"); + let msg = l10n.getFormatStr("selfxss.msg", [okstring]); + this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode, + doc.getElementById("webconsole-notificationbox"), + msg, okstring); this.inputNode.addEventListener("keypress", this._keyPress, false); this.inputNode.addEventListener("paste", this._onPaste); this.inputNode.addEventListener("drop", this._onPaste); diff --git a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties index 8b5252947728..273dc8a00c70 100644 --- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties +++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties @@ -103,3 +103,13 @@ scratchpad.panelLabel=Scratchpad Panel # tooltip of the tab when the Scratchpad is displayed inside the developer tools # window. scratchpad.tooltip=Scratchpad + +# LOCALIZATION NOTE (selfxss.msg): the text that is displayed when +# a new user of the developer tools pastes code into the console +# %1 is the text of selfxss.okstring +selfxss.msg=Scam Warning: Take care when pasting things you don't understand. This could allow attackers to steal your identity or take control of your computer. Please type '%S' in the scratchpad below to allow pasting. + +# LOCALIZATION NOTE (selfxss.msg): the string to be typed +# in by a new user of the developer tools when they receive the sefxss.msg prompt. +# Please avoid using non-keyboard characters here +selfxss.okstring=allow pasting diff --git a/toolkit/devtools/webconsole/utils.js b/toolkit/devtools/webconsole/utils.js index 2e239b1a249c..941270cd6d1c 100644 --- a/toolkit/devtools/webconsole/utils.js +++ b/toolkit/devtools/webconsole/utils.js @@ -570,7 +570,7 @@ let WebConsoleUtils = { * @param nsIDOMElement notificationBox * @returns A function to be added as a handler to 'paste' and 'drop' events on the input field */ - pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox){ + pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox, msg, okstring) { let handler = function WCU_pasteHandler(aEvent) { if (WebConsoleUtils.usageCount >= CONSOLE_ENTRY_THRESHOLD) { inputField.removeEventListener("paste", handler); @@ -582,9 +582,7 @@ let WebConsoleUtils = { aEvent.stopPropagation(); return false; } - let l10n = new WebConsoleUtils.l10n("chrome://browser/locale/devtools/webconsole.properties"); - let okstring = l10n.getStr("selfxss.okstring"); - let msg = l10n.getFormatStr("selfxss.msg", [okstring]); + let notification = notificationBox.appendNotification(msg, "selfxss-notification", null, notificationBox.PRIORITY_WARNING_HIGH, null, From 6745fc44689fae8c9006c9122ed7481e97e04bf4 Mon Sep 17 00:00:00 2001 From: Alex Bardas Date: Thu, 14 Aug 2014 10:57:00 -0400 Subject: [PATCH 65/86] Bug 1034679 - Add isEnabledStateLocked property to visually disable plug-ins with locked states in Add-ons Manager. r=bsmedberg --- dom/plugins/base/nsIPluginTag.idl | 7 ++++++- dom/plugins/base/nsPluginTags.cpp | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/dom/plugins/base/nsIPluginTag.idl b/dom/plugins/base/nsIPluginTag.idl index 40b44c2b9ef8..a5186ee810bb 100644 --- a/dom/plugins/base/nsIPluginTag.idl +++ b/dom/plugins/base/nsIPluginTag.idl @@ -5,7 +5,7 @@ #include "nsISupports.idl" -[scriptable, uuid(0e56f04d-cda4-4a55-ab83-e5e29ddd370e)] +[scriptable, uuid(231df043-3a32-43c4-aaac-7ad2da81e84f)] interface nsIPluginTag : nsISupports { // enabledState is stored as one of the following as an integer in prefs, @@ -25,6 +25,11 @@ interface nsIPluginTag : nsISupports */ readonly attribute boolean blocklisted; + /** + * true if the state is non-default and locked, false otherwise. + */ + readonly attribute boolean isEnabledStateLocked; + readonly attribute boolean disabled; readonly attribute boolean clicktoplay; attribute unsigned long enabledState; diff --git a/dom/plugins/base/nsPluginTags.cpp b/dom/plugins/base/nsPluginTags.cpp index fe59e08f7568..ed75ee4c8176 100644 --- a/dom/plugins/base/nsPluginTags.cpp +++ b/dom/plugins/base/nsPluginTags.cpp @@ -16,6 +16,7 @@ #include "nsPluginLogging.h" #include "nsNPAPIPlugin.h" #include "mozilla/Preferences.h" +#include "mozilla/unused.h" #include #include "mozilla/dom/EncodingUtils.h" @@ -340,6 +341,22 @@ nsPluginTag::GetBlocklisted(bool* aBlocklisted) return NS_OK; } +NS_IMETHODIMP +nsPluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked) +{ + *aIsEnabledStateLocked = false; + nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + + if (NS_WARN_IF(!prefs)) { + return NS_ERROR_FAILURE; + } + + unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(this).get(), + aIsEnabledStateLocked); + + return NS_OK; +} + bool nsPluginTag::IsClicktoplay() { From c252b0f4eb6ae7365168ca63c28eec9a9969a201 Mon Sep 17 00:00:00 2001 From: Alex Bardas Date: Mon, 11 Aug 2014 16:20:00 -0400 Subject: [PATCH 66/86] Bug 1034679 - Visually display that plug-in states are locked in Add-ons Manager. r=Unfocused --- .../mozapps/extensions/content/extensions.js | 11 +- .../mozapps/extensions/content/extensions.xml | 14 +- .../extensions/internal/PluginProvider.jsm | 3 + .../test/browser/browser-common.ini | 1 + .../test/browser/browser_CTP_plugins.js | 4 +- .../browser_plugin_enabled_state_locked.js | 121 ++++++++++++++++++ .../linux/mozapps/extensions/extensions.css | 4 + .../osx/mozapps/extensions/extensions.css | 4 + .../windows/mozapps/extensions/extensions.css | 4 + 9 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 0da4278c0302..c22a75f2e5b3 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -3106,13 +3106,13 @@ var gDetailView = { let menulist = document.getElementById("detail-state-menulist"); let addonType = AddonManager.addonTypes[this._addon.type]; - if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE && - (hasPermission(this._addon, "ask_to_activate") || - hasPermission(this._addon, "enable") || - hasPermission(this._addon, "disable"))) { + if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) { let askItem = document.getElementById("detail-ask-to-activate-menuitem"); let alwaysItem = document.getElementById("detail-always-activate-menuitem"); let neverItem = document.getElementById("detail-never-activate-menuitem"); + let hasActivatePermission = + ["ask_to_activate", "enable", "disable"].some(perm => hasPermission(this._addon, perm)); + if (this._addon.userDisabled === true) { menulist.selectedItem = neverItem; } else if (this._addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) { @@ -3120,7 +3120,10 @@ var gDetailView = { } else { menulist.selectedItem = alwaysItem; } + + menulist.disabled = !hasActivatePermission; menulist.hidden = false; + menulist.classList.add('no-auto-hide'); } else { menulist.hidden = true; } diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml index 0263df4b98f7..8969b56a9928 100644 --- a/toolkit/mozapps/extensions/content/extensions.xml +++ b/toolkit/mozapps/extensions/content/extensions.xml @@ -1306,10 +1306,7 @@ this.mAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO; let addonType = AddonManager.addonTypes[this.mAddon.type]; - if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE && - (this.hasPermission("ask_to_activate") || - this.hasPermission("enable") || - this.hasPermission("disable"))) { + if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) { this._enableBtn.disabled = true; this._disableBtn.disabled = true; this._askToActivateMenuitem.disabled = !this.hasPermission("ask_to_activate"); @@ -1322,10 +1319,13 @@ } else { this._stateMenulist.selectedItem = this._alwaysActivateMenuitem; } - this._stateMenulist.selectedItem.disabled = false; - this._stateMenulist.disabled = false; + let hasActivatePermission = + ["ask_to_activate", "enable", "disable"].some(perm => this.hasPermission(perm)); + this._stateMenulist.disabled = !hasActivatePermission; + this._stateMenulist.hidden = false; + this._stateMenulist.classList.add('no-auto-hide'); } else { - this._stateMenulist.disabled = true; + this._stateMenulist.hidden = true; if (this.hasPermission("enable")) { this._enableBtn.hidden = false; let tooltip = gViewController.commands["cmd_enableItem"] diff --git a/toolkit/mozapps/extensions/internal/PluginProvider.jsm b/toolkit/mozapps/extensions/internal/PluginProvider.jsm index 7b6e3353ffca..bf026f8a22d9 100644 --- a/toolkit/mozapps/extensions/internal/PluginProvider.jsm +++ b/toolkit/mozapps/extensions/internal/PluginProvider.jsm @@ -461,6 +461,9 @@ function PluginWrapper(aId, aName, aDescription, aTags) { this.__defineGetter__("permissions", function() { let permissions = 0; + if (aTags[0].isEnabledStateLocked) { + return permissions; + } if (!this.appDisabled) { if (this.userDisabled !== true) diff --git a/toolkit/mozapps/extensions/test/browser/browser-common.ini b/toolkit/mozapps/extensions/test/browser/browser-common.ini index a43aa6dc66ed..8463fbd90762 100644 --- a/toolkit/mozapps/extensions/test/browser/browser-common.ini +++ b/toolkit/mozapps/extensions/test/browser/browser-common.ini @@ -44,6 +44,7 @@ skip-if = buildapp == 'mulet' [browser_searching.js] [browser_sorting.js] [browser_sorting_plugins.js] +[browser_plugin_enabled_state_locked.js] skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] [browser_uninstalling.js] skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] diff --git a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js index 92d9fc3b0f63..d4a6b2b6b131 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js +++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js @@ -200,7 +200,7 @@ function part12(aWindow) { let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); pluginEl.parentNode.ensureElementIsVisible(pluginEl); let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); - is_element_hidden(menu, "part12: state menu should be hidden"); + is(menu.disabled, true, "part12: state menu should be disabled"); let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); @@ -209,7 +209,7 @@ function part12(aWindow) { function part13() { let menu = gManagerWindow.document.getElementById("detail-state-menulist"); - is_element_hidden(menu, "part13: detail state menu should be hidden"); + is(menu.disabled, true, "part13: detail state menu should be disabled"); setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() { run_next_test(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js new file mode 100644 index 000000000000..2eb8434e31a8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js @@ -0,0 +1,121 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that state menu is displayed correctly (enabled or disabled) in the add-on manager +// when the preference is unlocked / locked +const {classes: Cc, interfaces: Ci} = Components; +const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc); +const gIsOSX = ("nsILocalFileMac" in Ci); +const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) || + ("@mozilla.org/gio-service;1" in Cc); + +let gManagerWindow; +let gCategoryUtilities; +let gPluginElement; + +function getTestPluginPref() { + let prefix = "plugin.state."; + if (gIsWindows) + return prefix + "nptest"; + else if (gIsLinux) + return prefix + "libnptest"; + else + return prefix + "test"; +} + +registerCleanupFunction(() => { + Services.prefs.unlockPref(getTestPluginPref()); + Services.prefs.clearUserPref(getTestPluginPref()); +}); + +function getPlugins() { + let deferred = Promise.defer(); + AddonManager.getAddonsByTypes(["plugin"], plugins => deferred.resolve(plugins)); + return deferred.promise; +} + +function getTestPlugin(aPlugins) { + let testPluginId; + + for (let plugin of aPlugins) { + if (plugin.name == "Test Plug-in") { + testPluginId = plugin.id; + break; + } + } + + Assert.ok(testPluginId, "Test Plug-in should exist"); + + let pluginElement = get_addon_element(gManagerWindow, testPluginId); + pluginElement.parentNode.ensureElementIsVisible(pluginElement); + + return pluginElement; +} + +function checkStateMenu(locked) { + Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked, + "Preference lock state should be correct."); + let menuList = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "state-menulist"); + + is_element_visible(menuList, "State menu should be visible."); + Assert.equal(menuList.disabled, locked, + "State menu should" + (locked === true ? "" : " not") + " be disabled."); +} + +function checkStateMenuDetail(locked) { + Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked, + "Preference should be " + (locked === true ? "" : "un") + "locked."); + + // open details menu + let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn"); + is_element_visible(details, "Details link should be visible."); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, function() { + let menuList = gManagerWindow.document.getElementById("detail-state-menulist"); + is_element_visible(menuList, "Details state menu should be visible."); + Assert.equal(menuList.disabled, locked, + "Details state menu enabled state should be correct."); + deferred.resolve(); + }); + return deferred.promise; +} + +add_task(function* initializeState() { + Services.prefs.setIntPref(getTestPluginPref(), Ci.nsIPluginTag.STATE_ENABLED); + Services.prefs.unlockPref(getTestPluginPref()); + gManagerWindow = yield open_manager(); + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + yield gCategoryUtilities.openType("plugin"); + + let plugins = yield getPlugins(); + gPluginElement = getTestPlugin(plugins); +}); + +// Tests that plugin state menu is enabled if the preference is unlocked +add_task(function* taskCheckStateMenuIsEnabled() { + checkStateMenu(false); + yield checkStateMenuDetail(false); +}); + +// Lock the preference and then reload the plugin category +add_task(function* reinitializeState() { + // lock the preference + Services.prefs.lockPref(getTestPluginPref()); + yield gCategoryUtilities.openType("plugin"); + // Retrieve the test plugin element + let plugins = yield getPlugins(); + gPluginElement = getTestPlugin(plugins); +}); + +// Tests that plugin state menu is disabled if the preference is locked +add_task(function* taskCheckStateMenuIsDisabled() { + checkStateMenu(true); + yield checkStateMenuDetail(true); +}); + +add_task(function* testCleanup() { + yield close_manager(gManagerWindow); +}); diff --git a/toolkit/themes/linux/mozapps/extensions/extensions.css b/toolkit/themes/linux/mozapps/extensions/extensions.css index dab9a6c476dc..a1f344161672 100644 --- a/toolkit/themes/linux/mozapps/extensions/extensions.css +++ b/toolkit/themes/linux/mozapps/extensions/extensions.css @@ -884,6 +884,10 @@ setting[type="radio"] > radiogroup { display: none; } +.addon-control.no-auto-hide { + display: block; +} + .addon-control.enable { list-style-image: url("moz-icon://stock/gtk-yes?size=button"); } diff --git a/toolkit/themes/osx/mozapps/extensions/extensions.css b/toolkit/themes/osx/mozapps/extensions/extensions.css index e9e83e1f450d..1d8fe5936b67 100644 --- a/toolkit/themes/osx/mozapps/extensions/extensions.css +++ b/toolkit/themes/osx/mozapps/extensions/extensions.css @@ -1108,6 +1108,10 @@ setting[type="radio"] > radiogroup { display: none; } +.addon-control.no-auto-hide { + display: block; +} + button.button-link { -moz-appearance: none; background: transparent; diff --git a/toolkit/themes/windows/mozapps/extensions/extensions.css b/toolkit/themes/windows/mozapps/extensions/extensions.css index ac49e3a58147..7dbaa055b794 100644 --- a/toolkit/themes/windows/mozapps/extensions/extensions.css +++ b/toolkit/themes/windows/mozapps/extensions/extensions.css @@ -1124,6 +1124,10 @@ menulist { /* Fixes some styling inconsistencies */ display: none; } +.addon-control.no-auto-hide { + display: block; +} + button.button-link { -moz-appearance: none; background: transparent; From 8b62e3b1a318d7ab626842f3bfce59fabc68b471 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 12 Aug 2014 16:59:12 -0700 Subject: [PATCH 67/86] Bug 1037358 - Fix up ArrayBufferObject malloc accounting, assigning to correct zone for all types, r=terrence,froydnj,smaug --- content/base/src/nsXMLHttpRequest.cpp | 6 ++- js/src/jsapi.h | 27 +++------- js/src/vm/ArrayBufferObject.cpp | 51 ++++--------------- .../osfile/NativeOSFileInternals.cpp | 2 +- 4 files changed, 23 insertions(+), 63 deletions(-) diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index 554eb7279c15..2f980968a020 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -3973,11 +3973,15 @@ ArrayBufferBuilder::setCapacity(uint32_t aNewCap) { MOZ_ASSERT(!mMapPtr); - uint8_t *newdata = (uint8_t *) JS_ReallocateArrayBufferContents(nullptr, aNewCap, mDataPtr, mCapacity); + uint8_t *newdata = (uint8_t *) realloc(mDataPtr, aNewCap); if (!newdata) { return false; } + if (aNewCap > mCapacity) { + memset(newdata + mCapacity, 0, aNewCap - mCapacity); + } + mDataPtr = newdata; mCapacity = aNewCap; if (mLength > aNewCap) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 8956d8a829f7..39e13d748b1a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3216,8 +3216,9 @@ JS_PUBLIC_API(void) JS_SetAllNonReservedSlotsToUndefined(JSContext *cx, JSObject *objArg); /* - * Create a new array buffer with the given contents. On success, the ownership - * is transferred to the new array buffer. + * Create a new array buffer with the given contents. It must be legal to pass + * these contents to free(). On success, the ownership is transferred to the + * new array buffer. */ extern JS_PUBLIC_API(JSObject *) JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *contents); @@ -3232,25 +3233,9 @@ extern JS_PUBLIC_API(void *) JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj); /* - * Allocate memory that may be eventually passed to - * JS_NewArrayBufferWithContents. |maybecx| is optional; if a non-nullptr cx is - * given, it will be used for memory accounting and OOM reporting. |nbytes| is - * the number of payload bytes required. - */ -extern JS_PUBLIC_API(void *) -JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes); - -/* - * Reallocate memory allocated by JS_AllocateArrayBufferContents, growing or - * shrinking it as appropriate. If oldContents is null then this behaves like - * JS_AllocateArrayBufferContents. - */ -extern JS_PUBLIC_API(void *) -JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void *oldContents, uint32_t oldNbytes); - -/* - * Create a new mapped array buffer with the given memory mapped contents. On success, - * the ownership is transferred to the new mapped array buffer. + * Create a new mapped array buffer with the given memory mapped contents. It + * must be legal to free the contents pointer by unmapping it. On success, + * ownership is transferred to the new mapped array buffer. */ extern JS_PUBLIC_API(JSObject *) JS_NewMappedArrayBufferWithContents(JSContext *cx, size_t nbytes, void *contents); diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 5c9335de43d7..8d82501c1e46 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -267,32 +267,11 @@ ArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value *vp) } static ArrayBufferObject::BufferContents -AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes) +AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes) { - void *p = maybecx ? maybecx->runtime()->callocCanGC(nbytes) : js_calloc(nbytes); - if (!p && maybecx) - js_ReportOutOfMemory(maybecx); - - return ArrayBufferObject::BufferContents::create(p); -} - -/* - * Note that some callers are allowed to pass in a nullptr cx, so we allocate - * with the cx if available and fall back to the runtime. If oldptr is given, - * it's expected to be a previously-allocated contents pointer that we then - * realloc. - */ -static ArrayBufferObject::BufferContents -ReallocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr, size_t oldnbytes) -{ - void *p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, nbytes) : js_realloc(oldptr, nbytes); - - // if we grew the array, we need to set the new bytes to 0 - if (p && nbytes > oldnbytes) - memset(reinterpret_cast(p) + oldnbytes, 0, nbytes - oldnbytes); - - if (!p && maybecx) - js_ReportOutOfMemory(maybecx); + void *p = cx->runtime()->callocCanGC(nbytes); + if (!p) + js_ReportOutOfMemory(cx); return ArrayBufferObject::BufferContents::create(p); } @@ -664,7 +643,13 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, BufferContents content size_t nslots = reservedSlots; bool allocated = false; - if (!contents) { + if (contents) { + // The ABO is taking ownership, so account the bytes against the zone. + size_t nAllocated = nbytes; + if (contents.kind() & MAPPED_BUFFER) + nAllocated = JS_ROUNDUP(nbytes, js::gc::SystemPageSize()); + cx->zone()->updateMallocCounter(nAllocated); + } else { size_t usableSlots = JSObject::MAX_FIXED_SLOTS - reservedSlots; if (nbytes <= usableSlots * sizeof(Value)) { int newSlots = (nbytes - 1) / sizeof(Value) + 1; @@ -697,8 +682,6 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, BufferContents content memset(data, 0, nbytes); obj->initialize(nbytes, BufferContents::createUnowned(data), DoesntOwnData); } else { - if (contents.kind() & MAPPED_BUFFER) - JS_updateMallocCounter(cx, JS_ROUNDUP(nbytes, js::gc::SystemPageSize())); obj->initialize(nbytes, contents, OwnsData); } @@ -1157,18 +1140,6 @@ JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *data) return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject); } -JS_PUBLIC_API(void *) -JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes) -{ - return AllocateArrayBufferContents(maybecx, nbytes).data(); -} - -JS_PUBLIC_API(void *) -JS_ReallocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldContents, uint32_t oldNbytes) -{ - return ReallocateArrayBufferContents(maybecx, nbytes, oldContents, oldNbytes).data(); -} - JS_FRIEND_API(bool) JS_IsArrayBufferObject(JSObject *obj) { diff --git a/toolkit/components/osfile/NativeOSFileInternals.cpp b/toolkit/components/osfile/NativeOSFileInternals.cpp index 6b10e4bd5b8f..311209c961a7 100644 --- a/toolkit/components/osfile/NativeOSFileInternals.cpp +++ b/toolkit/components/osfile/NativeOSFileInternals.cpp @@ -114,7 +114,7 @@ struct ScopedArrayBufferContents: public Scoped bool Allocate(uint32_t length) { dispose(); ArrayBufferContents& value = rwget(); - void *ptr = JS_AllocateArrayBufferContents(/*no context available*/nullptr, length); + void *ptr = calloc(1, length); if (ptr) { value.data = (uint8_t *) ptr; value.nbytes = length; From 02337431c7297effb153c3b3635ff180e761c92f Mon Sep 17 00:00:00 2001 From: Alex Bardas Date: Thu, 14 Aug 2014 15:48:00 -0400 Subject: [PATCH 68/86] Bug 1041678 - CTRL/Command K should goto search bar in new tab if open, rather than opening about:home. r=Gijs, r=adw --- browser/base/content/browser.js | 15 ++++++++++++++- browser/base/content/content.js | 8 ++++++++ browser/base/content/newtab/search.js | 4 ++++ .../content/test/general/browser_aboutHome.js | 16 ++++++++++++++++ browser/base/content/test/general/head.js | 6 ++++++ .../content/test/newtab/browser_newtab_search.js | 10 ++++++++++ browser/modules/AboutHome.jsm | 9 +++++++++ browser/modules/ContentSearch.jsm | 11 +++++++++++ 8 files changed, 78 insertions(+), 1 deletion(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 363b3bb45c7f..48234f368b6a 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -23,6 +23,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils", "resource://gre/modules/ShortcutUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager", "resource://gre/modules/GMPInstallManager.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch", + "resource:///modules/ContentSearch.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "AboutHome", + "resource:///modules/AboutHome.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "gDNSService", "@mozilla.org/network/dns-service;1", "nsIDNSService"); @@ -3095,8 +3099,17 @@ const BrowserSearch = { } #endif let openSearchPageIfFieldIsNotActive = function(aSearchBar) { - if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) + let doc = gBrowser.selectedBrowser.contentDocument; + let url = doc.documentURI.toLowerCase(); + let mm = gBrowser.selectedBrowser.messageManager; + + if (url === "about:home") { + AboutHome.focusInput(mm); + } else if (url === "about:newtab") { + ContentSearch.focusInput(mm); + } else if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) { openUILinkIn("about:home", "current"); + } }; let searchBar = this.searchBar; diff --git a/browser/base/content/content.js b/browser/base/content/content.js index bc3fe9b930ba..d4461de6ef6d 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -106,6 +106,9 @@ let AboutHomeListener = { case "AboutHome:Update": this.onUpdate(aMessage.data); break; + case "AboutHome:FocusInput": + this.onFocusInput(); + break; } }, @@ -138,6 +141,7 @@ let AboutHomeListener = { doc.documentElement.setAttribute("hasBrowserHandlers", "true"); let self = this; addMessageListener("AboutHome:Update", self); + addMessageListener("AboutHome:FocusInput", self); addEventListener("click", this.onClick, true); addEventListener("pagehide", function onPageHide(event) { if (event.target.defaultView.frameElement) @@ -212,6 +216,10 @@ let AboutHomeListener = { break; } }, + + onFocusInput: function () { + content.document.getElementById("searchText").focus(); + }, }; AboutHomeListener.init(this); diff --git a/browser/base/content/newtab/search.js b/browser/base/content/newtab/search.js index 2d29c65a4a7d..5038b633009c 100644 --- a/browser/base/content/newtab/search.js +++ b/browser/base/content/newtab/search.js @@ -76,6 +76,10 @@ let gSearch = { } }, + onFocusInput: function () { + this._nodes.text.focus(); + }, + _nodeIDSuffixes: [ "form", "logo", diff --git a/browser/base/content/test/general/browser_aboutHome.js b/browser/base/content/test/general/browser_aboutHome.js index d0b1f4cd9544..9b51e0fa22b7 100644 --- a/browser/base/content/test/general/browser_aboutHome.js +++ b/browser/base/content/test/general/browser_aboutHome.js @@ -419,6 +419,22 @@ let gTests = [ }); } }, +{ + desc: "Cmd+k should focus the search bar element", + setup: function () {}, + run: Task.async(function* () { + let doc = gBrowser.selectedTab.linkedBrowser.contentDocument; + let logo = doc.getElementById("brandLogo"); + let searchInput = doc.getElementById("searchText"); + + EventUtils.synthesizeMouseAtCenter(logo, {}); + isnot(searchInput, doc.activeElement, "Search input should not be the active element."); + + EventUtils.synthesizeKey("k", { accelKey: true }); + yield promiseWaitForCondition(() => doc.activeElement === searchInput); + is(searchInput, doc.activeElement, "Search input should be the active element."); + }) +}, ]; diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js index 15298e4eba85..05d6675b16fb 100644 --- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -82,6 +82,12 @@ function waitForCondition(condition, nextTest, errorMsg) { var moveOn = function() { clearInterval(interval); nextTest(); }; } +function promiseWaitForCondition(aConditionFn) { + let deferred = Promise.defer(); + waitForCondition(aConditionFn, deferred.resolve, "Condition didn't pass."); + return deferred.promise; +} + function getTestPlugin(aName) { var pluginName = aName || "Test Plug-in"; var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); diff --git a/browser/base/content/test/newtab/browser_newtab_search.js b/browser/base/content/test/newtab/browser_newtab_search.js index 1e7a65da4c0e..de652e813ab4 100644 --- a/browser/base/content/test/newtab/browser_newtab_search.js +++ b/browser/base/content/test/newtab/browser_newtab_search.js @@ -186,6 +186,16 @@ function runTests() { EventUtils.synthesizeKey("VK_DELETE", {}); ok(table.hidden, "Search suggestion table hidden"); + // Focus a different element than the search input. + let btn = getContentDocument().getElementById("newtab-customize-button"); + yield promiseClick(btn).then(TestRunner.next); + + isnot(input, getContentDocument().activeElement, "Search input should not be focused"); + // Test that Ctrl/Cmd + K will focus the input field. + EventUtils.synthesizeKey("k", { accelKey: true }); + yield promiseSearchEvents(["FocusInput"]).then(TestRunner.next); + is(input, getContentDocument().activeElement, "Search input should be focused"); + // Done. Revert the current engine and remove the new engines. Services.search.currentEngine = oldCurrentEngine; yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next); diff --git a/browser/modules/AboutHome.jsm b/browser/modules/AboutHome.jsm index 75261fcc4153..ea00029ab54c 100644 --- a/browser/modules/AboutHome.jsm +++ b/browser/modules/AboutHome.jsm @@ -251,4 +251,13 @@ let AboutHome = { Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x); }); }, + + /** + * Focuses the search input in the page with the given message manager. + * @param messageManager + * The MessageManager object of the selected browser. + */ + focusInput: function (messageManager) { + messageManager.sendAsyncMessage("AboutHome:FocusInput"); + } }; diff --git a/browser/modules/ContentSearch.jsm b/browser/modules/ContentSearch.jsm index ee5ca9c79753..d6828d7a8266 100644 --- a/browser/modules/ContentSearch.jsm +++ b/browser/modules/ContentSearch.jsm @@ -94,6 +94,17 @@ this.ContentSearch = { Services.obs.addObserver(this, "browser-search-engine-modified", false); }, + /** + * Focuses the search input in the page with the given message manager. + * @param messageManager + * The MessageManager object of the selected browser. + */ + focusInput: function (messageManager) { + messageManager.sendAsyncMessage(OUTBOUND_MESSAGE, { + type: "FocusInput" + }); + }, + receiveMessage: function (msg) { // Add a temporary event handler that exists only while the message is in // the event queue. If the message's source docshell changes browsers in From 2ab7a10626b665cc7bb29986524bb613115401ed Mon Sep 17 00:00:00 2001 From: Jordan Santell Date: Wed, 13 Aug 2014 10:55:00 -0400 Subject: [PATCH 69/86] Bug 1052028 - Remove 'Node' from displayed node names in web audio editor. r=vp --- browser/devtools/webaudioeditor/webaudioeditor-view.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/browser/devtools/webaudioeditor/webaudioeditor-view.js b/browser/devtools/webaudioeditor/webaudioeditor-view.js index 4fbe8d8eac48..8b69fc44cf86 100644 --- a/browser/devtools/webaudioeditor/webaudioeditor-view.js +++ b/browser/devtools/webaudioeditor/webaudioeditor-view.js @@ -156,7 +156,11 @@ let WebAudioGraphView = { AudioNodes.forEach(node => { // Add node to graph - graph.addNode(node.id, { label: node.type, id: node.id }); + graph.addNode(node.id, { + type: node.type, // Just for storing type data + label: node.type.replace(/Node$/, ""), // Displayed in SVG node + id: node.id // Identification + }); // Add all of the connections from this node to the edge array to be added // after all the nodes are added, otherwise edges will attempted to be created @@ -177,7 +181,7 @@ let WebAudioGraphView = { let svgNodes = oldDrawNodes(graph, root); svgNodes.attr("class", (n) => { let node = graph.node(n); - return "audionode type-" + node.label; + return "audionode type-" + node.type; }); svgNodes.attr("data-id", (n) => { let node = graph.node(n); From 1c39379cd660e61b2b4d7e721af2377275c21c08 Mon Sep 17 00:00:00 2001 From: Max Vujovic Date: Fri, 15 Aug 2014 10:43:42 -0700 Subject: [PATCH 70/86] Bug 948265 - Add NOT_IMPLEMENTED return value for each CSS filter in nsCSSFilterInstance. r=longsonr --- layout/svg/nsCSSFilterInstance.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/layout/svg/nsCSSFilterInstance.cpp b/layout/svg/nsCSSFilterInstance.cpp index 94a6bae95dce..7326f98aa797 100644 --- a/layout/svg/nsCSSFilterInstance.cpp +++ b/layout/svg/nsCSSFilterInstance.cpp @@ -39,16 +39,23 @@ nsCSSFilterInstance::BuildPrimitives(nsTArray& aPrim result = SetAttributesForBlur(descr); break; case NS_STYLE_FILTER_BRIGHTNESS: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_CONTRAST: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_DROP_SHADOW: descr = CreatePrimitiveDescription(PrimitiveType::DropShadow, aPrimitiveDescrs); result = SetAttributesForDropShadow(descr); break; case NS_STYLE_FILTER_GRAYSCALE: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_HUE_ROTATE: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_INVERT: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_OPACITY: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_SATURATE: + return NS_ERROR_NOT_IMPLEMENTED; case NS_STYLE_FILTER_SEPIA: return NS_ERROR_NOT_IMPLEMENTED; default: From 7ecd01e5fb862c49597c0c14cf1dfa5852356222 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Thu, 14 Aug 2014 13:50:25 -0400 Subject: [PATCH 71/86] Bug 1049501: Don't let the GMPThread event loop recurse while handling IPDL shutdowns r=bsmedberg --- content/media/gmp/GMPVideoEncoderParent.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/content/media/gmp/GMPVideoEncoderParent.cpp b/content/media/gmp/GMPVideoEncoderParent.cpp index 816a40cc8b8f..34faad7d35ad 100644 --- a/content/media/gmp/GMPVideoEncoderParent.cpp +++ b/content/media/gmp/GMPVideoEncoderParent.cpp @@ -12,6 +12,7 @@ #include "nsAutoRef.h" #include "GMPParent.h" #include "mozilla/gmp/GMPTypes.h" +#include "nsThread.h" #include "nsThreadUtils.h" #include "runnable_utils.h" @@ -72,7 +73,9 @@ GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin) GMPVideoEncoderParent::~GMPVideoEncoderParent() { - mEncodedThread->Shutdown(); + if (mEncodedThread) { + mEncodedThread->Shutdown(); + } } GMPVideoHostImpl& @@ -238,6 +241,12 @@ GMPVideoEncoderParent::Shutdown() } } +static void +ShutdownEncodedThread(nsCOMPtr& aThread) +{ + aThread->Shutdown(); +} + // Note: Keep this sync'd up with Shutdown void GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) @@ -249,6 +258,15 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) mCallback->Terminated(); mCallback = nullptr; } + // Must be shut down before VideoEncoderDestroyed(), since this can recurse + // the GMPThread event loop. See bug 1049501 + if (mEncodedThread) { + // Can't get it to allow me to use WrapRunnable with a nsCOMPtr() + NS_DispatchToMainThread( + WrapRunnableNM >(&ShutdownEncodedThread, mEncodedThread)); + mEncodedThread = nullptr; + } if (mPlugin) { // Ignore any return code. It is OK for this to fail without killing the process. mPlugin->VideoEncoderDestroyed(this); From bb8bc134989391f287d807eba49620720cc8784c Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Fri, 15 Aug 2014 18:23:16 +0100 Subject: [PATCH 72/86] Bug 1010741 - Change text appearance in toolbar (r=mcomella) --HG-- rename : mobile/android/base/resources/values-v16/styles.xml => mobile/android/base/resources/values-large-v16/styles.xml --- .../layout/toolbar_display_layout.xml | 8 +------- .../resources/layout/toolbar_edit_layout.xml | 12 +---------- .../resources/values-large-v11/styles.xml | 4 ++++ .../resources/values-large-v16/styles.xml | 13 ++++++++++++ .../base/resources/values-v16/styles.xml | 5 +++++ .../android/base/resources/values/styles.xml | 20 ++++++++++++++++++- 6 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 mobile/android/base/resources/values-large-v16/styles.xml diff --git a/mobile/android/base/resources/layout/toolbar_display_layout.xml b/mobile/android/base/resources/layout/toolbar_display_layout.xml index 8ff1d8acc896..e2fdeba04914 100644 --- a/mobile/android/base/resources/layout/toolbar_display_layout.xml +++ b/mobile/android/base/resources/layout/toolbar_display_layout.xml @@ -26,17 +26,11 @@ android:visibility="gone"/> diff --git a/mobile/android/base/resources/values-large-v11/styles.xml b/mobile/android/base/resources/values-large-v11/styles.xml index b2f5e523886a..faadf10110c4 100644 --- a/mobile/android/base/resources/values-large-v11/styles.xml +++ b/mobile/android/base/resources/values-large-v11/styles.xml @@ -125,4 +125,8 @@ center + + diff --git a/mobile/android/base/resources/values-large-v16/styles.xml b/mobile/android/base/resources/values-large-v16/styles.xml new file mode 100644 index 000000000000..1c57a046e746 --- /dev/null +++ b/mobile/android/base/resources/values-large-v16/styles.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/mobile/android/base/resources/values-v16/styles.xml b/mobile/android/base/resources/values-v16/styles.xml index fbf845dcd93a..514e9246b2cd 100644 --- a/mobile/android/base/resources/values-v16/styles.xml +++ b/mobile/android/base/resources/values-v16/styles.xml @@ -17,4 +17,9 @@ sans-serif-light + + diff --git a/mobile/android/base/resources/values/styles.xml b/mobile/android/base/resources/values/styles.xml index ae6d740d24d6..bedc19d68fdc 100644 --- a/mobile/android/base/resources/values/styles.xml +++ b/mobile/android/base/resources/values/styles.xml @@ -388,6 +388,10 @@ @color/doorhanger_link + + + + + - - diff --git a/mobile/android/base/resources/values-large-v16/styles.xml b/mobile/android/base/resources/values-large-v16/styles.xml deleted file mode 100644 index 1c57a046e746..000000000000 --- a/mobile/android/base/resources/values-large-v16/styles.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/mobile/android/base/resources/values-v16/styles.xml b/mobile/android/base/resources/values-v16/styles.xml index 514e9246b2cd..fbf845dcd93a 100644 --- a/mobile/android/base/resources/values-v16/styles.xml +++ b/mobile/android/base/resources/values-v16/styles.xml @@ -17,9 +17,4 @@ sans-serif-light - - diff --git a/mobile/android/base/resources/values/colors.xml b/mobile/android/base/resources/values/colors.xml index 8f93c24eb64e..33dea0367127 100644 --- a/mobile/android/base/resources/values/colors.xml +++ b/mobile/android/base/resources/values/colors.xml @@ -4,8 +4,8 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - #FFF5F5F5 - #FFEBEBF0 + #FFECF0F3 + #FFCED7DE #FF292C29 #FF363B40 #33000000 diff --git a/mobile/android/base/resources/values/styles.xml b/mobile/android/base/resources/values/styles.xml index bedc19d68fdc..ae6d740d24d6 100644 --- a/mobile/android/base/resources/values/styles.xml +++ b/mobile/android/base/resources/values/styles.xml @@ -388,10 +388,6 @@ @color/doorhanger_link - - - - -