diff --git a/accessible/src/xul/XULSelectControlAccessible.cpp b/accessible/src/xul/XULSelectControlAccessible.cpp index aaa2db4df8cf..2b492bd13ebc 100644 --- a/accessible/src/xul/XULSelectControlAccessible.cpp +++ b/accessible/src/xul/XULSelectControlAccessible.cpp @@ -70,7 +70,7 @@ XULSelectControlAccessible::SelectedItems() xulMultiSelect->GetSelectedCount(&length); for (PRInt32 index = 0; index < length; index++) { nsCOMPtr itemElm; - xulMultiSelect->GetSelectedItem(index, getter_AddRefs(itemElm)); + xulMultiSelect->MultiGetSelectedItem(index, getter_AddRefs(itemElm)); nsCOMPtr itemNode(do_QueryInterface(itemElm)); Accessible* item = mDoc->GetAccessible(itemNode); if (item) @@ -78,15 +78,15 @@ XULSelectControlAccessible::SelectedItems() false); } } else { // Single select? - nsCOMPtr itemElm; - mSelectControl->GetSelectedItem(getter_AddRefs(itemElm)); - nsCOMPtr itemNode(do_QueryInterface(itemElm)); - if(itemNode) { - Accessible* item = mDoc->GetAccessible(itemNode); - if (item) - selectedItems->AppendElement(static_cast(item), - false); - } + nsCOMPtr itemElm; + mSelectControl->GetSelectedItem(getter_AddRefs(itemElm)); + nsCOMPtr itemNode(do_QueryInterface(itemElm)); + if (itemNode) { + Accessible* item = mDoc->GetAccessible(itemNode); + if (item) + selectedItems->AppendElement(static_cast(item), + false); + } } nsIMutableArray* items = nullptr; @@ -102,7 +102,7 @@ XULSelectControlAccessible::GetSelectedItem(PRUint32 aIndex) nsCOMPtr itemElm; if (multiSelectControl) - multiSelectControl->GetSelectedItem(aIndex, getter_AddRefs(itemElm)); + multiSelectControl->MultiGetSelectedItem(aIndex, getter_AddRefs(itemElm)); else if (aIndex == 0) mSelectControl->GetSelectedItem(getter_AddRefs(itemElm)); diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index c9b31c510dcb..1643b1515669 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1172,6 +1172,8 @@ pref("image.mem.max_decoded_image_kb", 256000); // Example social provider pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}"); +// Comma-separated list of nsIURI::prePaths that are allowed to activate +// built-in social functionality. +pref("social.activation.whitelist", "https://motown-dev.mozillalabs.com"); pref("social.sidebar.open", true); -pref("browser.social.whitelist", ""); pref("social.active", false); diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index 5fa88f5c3b1e..ef886afe3707 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -113,7 +113,7 @@ let SocialUI = { // Check that the associated document's origin is in our whitelist let prePath = targetDoc.documentURIObject.prePath; - let whitelist = Services.prefs.getCharPref("browser.social.whitelist"); + let whitelist = Services.prefs.getCharPref("social.activation.whitelist"); if (whitelist.split(",").indexOf(prePath) == -1) return; diff --git a/build/ConfigStatus.py b/build/ConfigStatus.py index 6b53b07c2380..2da626a34053 100644 --- a/build/ConfigStatus.py +++ b/build/ConfigStatus.py @@ -99,28 +99,32 @@ class ConfigEnvironment(object): directory. It preprocesses files from the source directory and stores the result in the object directory. - There are two types of files: config files and config headers, - each treated through a different member function. + There are two types of files: config files and config headers, + each treated through a different member function. - Creating a ConfigEnvironment requires a few arguments: - - topsrcdir and topobjdir are, respectively, the top source and - the top object directory. - - defines is a list of (name, value) tuples. In autoconf, these are - set with AC_DEFINE and AC_DEFINE_UNQUOTED - - non_global_defines are a list of names appearing in defines above - that are not meant to be exported in ACDEFINES and ALLDEFINES (see - below) - - substs is a list of (name, value) tuples. In autoconf, these are - set with AC_SUBST. + Creating a ConfigEnvironment requires a few arguments: + - topsrcdir and topobjdir are, respectively, the top source and + the top object directory. + - defines is a list of (name, value) tuples. In autoconf, these are + set with AC_DEFINE and AC_DEFINE_UNQUOTED + - non_global_defines are a list of names appearing in defines above + that are not meant to be exported in ACDEFINES and ALLDEFINES (see + below) + - substs is a list of (name, value) tuples. In autoconf, these are + set with AC_SUBST. - ConfigEnvironment automatically defines two additional substs variables - from all the defines not appearing in non_global_defines: - - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on - preprocessor command lines. The order in which defines were given - when creating the ConfigEnvironment is preserved. - - ALLDEFINES contains the defines in the form #define NAME VALUE, in - sorted order, for use in config files, for an automatic listing of - defines. + ConfigEnvironment automatically defines two additional substs variables + from all the defines not appearing in non_global_defines: + - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on + preprocessor command lines. The order in which defines were given + when creating the ConfigEnvironment is preserved. + - ALLDEFINES contains the defines in the form #define NAME VALUE, in + sorted order, for use in config files, for an automatic listing of + defines. + and another additional subst variable from all the other substs: + - ALLSUBSTS contains the substs in the form NAME = VALUE, in sorted + order, for use in autoconf.mk. It includes ACDEFINES, but doesn't + include ALLDEFINES. ConfigEnvironment expects a "top_srcdir" subst to be set with the top source directory, in msys format on windows. It is used to derive a @@ -136,6 +140,7 @@ class ConfigEnvironment(object): self.topobjdir = topobjdir global_defines = [name for name, value in defines if not name in non_global_defines] self.substs['ACDEFINES'] = ' '.join(["-D%s=%s" % (name, shell_escape(self.defines[name])) for name in global_defines]) + self.substs['ALLSUBSTS'] = '\n'.join(sorted(["%s = %s" % (name, self.substs[name]) for name in self.substs])) self.substs['ALLDEFINES'] = '\n'.join(sorted(["#define %s %s" % (name, self.defines[name]) for name in global_defines])) def get_relative_srcdir(self, file): diff --git a/build/autoconf/mozconfig2client-mk b/build/autoconf/mozconfig2client-mk index dc6ace9378ae..acf0ec18d418 100755 --- a/build/autoconf/mozconfig2client-mk +++ b/build/autoconf/mozconfig2client-mk @@ -32,7 +32,7 @@ mk_add_options() { do # Escape shell characters, space, tab, dollar, quote, backslash, # and substitute '@@' with '$()'. - _opt=`echo "$_opt" | sed -e 's/\([\"\\]\)/\\\1/g; s/@\([^@]*\)@/\$(\1)/g;'` + _opt=`echo "$_opt" | sed -e 's/\([\"\\]\)/\\\\\1/g; s/@\([^@]*\)@/\$(\1)/g;'` echo $_opt; opts="${opts:+$opts^}$_opt"; done diff --git a/build/mobile/devicemanagerSUT.py b/build/mobile/devicemanagerSUT.py index f5d6ea6e42c2..d1e7ae46d76d 100644 --- a/build/mobile/devicemanagerSUT.py +++ b/build/mobile/devicemanagerSUT.py @@ -807,7 +807,8 @@ class DeviceManagerSUT(DeviceManager): retVal = None if data: retVal = data.strip() - if (self.debug >= 3): print "remote hash returned: '" + retVal + "'" + if self.debug >= 3: + print "remote hash returned: '%s'" % retVal return retVal # Gets the device root for the testing area on the device diff --git a/build/mozconfig.vs2010-common b/build/mozconfig.vs2010-common new file mode 100644 index 000000000000..9806ae24282b --- /dev/null +++ b/build/mozconfig.vs2010-common @@ -0,0 +1,8 @@ +# Pymake needs Windows-style paths. Use cmd.exe to hack around this. +mk_export_correct_style() { + if test -n "${_PYMAKE}"; then + mk_add_options "export $1=$(cmd.exe //c echo %$1%)" + else + mk_add_options "export $1=$(eval echo \$$1)" + fi +} diff --git a/build/pymake/mkformat.py b/build/pymake/mkformat.py new file mode 100755 index 000000000000..41dd761b2f2e --- /dev/null +++ b/build/pymake/mkformat.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +import sys +import pymake.parser + +filename = sys.argv[1] +source = None + +with open(filename, 'rU') as fh: + source = fh.read() + +statements = pymake.parser.parsestring(source, filename) +print statements.to_source() diff --git a/build/pymake/pymake/data.py b/build/pymake/pymake/data.py index b9edd7513ad7..c85d6943431e 100644 --- a/build/pymake/pymake/data.py +++ b/build/pymake/pymake/data.py @@ -62,10 +62,84 @@ def _if_else(c, t, f): return t() return f() -class StringExpansion(object): + +class BaseExpansion(object): + """Base class for expansions. + + A make expansion is the parsed representation of a string, which may + contain references to other elements. + """ + + @property + def is_static_string(self): + """Returns whether the expansion is composed of static string content. + + This is always True for StringExpansion. It will be True for Expansion + only if all elements of that Expansion are static strings. + """ + raise Exception('Must be implemented in child class.') + + def functions(self, descend=False): + """Obtain all functions inside this expansion. + + This is a generator for pymake.functions.Function instances. + + By default, this only returns functions existing as the primary + elements of this expansion. If `descend` is True, it will descend into + child expansions and extract all functions in the tree. + """ + # An empty generator. Yeah, it's weird. + for x in []: + yield x + + def variable_references(self, descend=False): + """Obtain all variable references in this expansion. + + This is a generator for pymake.functionsVariableRef instances. + + To retrieve the names of variables, simply query the `vname` field on + the returned instances. Most of the time these will be StringExpansion + instances. + """ + for f in self.functions(descend=descend): + if not isinstance(f, functions.VariableRef): + continue + + yield f + + @property + def is_filesystem_dependent(self): + """Whether this expansion may query the filesystem for evaluation. + + This effectively asks "is any function in this expansion dependent on + the filesystem. + """ + for f in self.functions(descend=True): + if f.is_filesystem_dependent: + return True + + return False + + @property + def is_shell_dependent(self): + """Whether this expansion may invoke a shell for evaluation.""" + + for f in self.functions(descend=True): + if isinstance(f, functions.ShellFunction): + return True + + return False + + +class StringExpansion(BaseExpansion): + """An Expansion representing a static string. + + This essentially wraps a single str instance. + """ + __slots__ = ('loc', 's',) simple = True - + def __init__(self, s, loc): assert isinstance(s, str) self.s = s @@ -94,6 +168,10 @@ class StringExpansion(object): e.appendstr(self.s) return e + @property + def is_static_string(self): + return True + def __len__(self): return 1 @@ -104,9 +182,31 @@ class StringExpansion(object): def __repr__(self): return "Exp<%s>(%r)" % (self.loc, self.s) -class Expansion(list): - """ - A representation of expanded data, such as that for a recursively-expanded variable, a command, etc. + def __eq__(self, other): + """We only compare the string contents.""" + return self.s == other + + def __ne__(self, other): + return not self.__eq__(other) + + def to_source(self, escape_variables=False, escape_comments=False): + s = self.s + + if escape_comments: + s = s.replace('#', '\\#') + + if escape_variables: + return s.replace('$', '$$') + + return s + + +class Expansion(BaseExpansion, list): + """A representation of expanded data. + + This is effectively an ordered list of StringExpansion and + pymake.function.Function instances. Every item in the collection appears in + the same context in a make file. """ __slots__ = ('loc',) @@ -232,9 +332,91 @@ class Expansion(list): def resolvesplit(self, makefile, variables, setting=[]): return self.resolvestr(makefile, variables, setting).split() + @property + def is_static_string(self): + """An Expansion is static if all its components are strings, not + functions.""" + for e, is_func in self: + if is_func: + return False + + return True + + def functions(self, descend=False): + for e, is_func in self: + if is_func: + yield e + + if descend: + for exp in e.expansions(descend=True): + for f in exp.functions(descend=True): + yield f + def __repr__(self): return "" % ([e for e, isfunc in self],) + def to_source(self, escape_variables=False, escape_comments=False): + parts = [] + for e, is_func in self: + if is_func: + parts.append(e.to_source()) + continue + + if escape_variables: + parts.append(e.replace('$', '$$')) + continue + + parts.append(e) + + return ''.join(parts) + + def __eq__(self, other): + if not isinstance(other, (Expansion, StringExpansion)): + return False + + # Expansions are equivalent if adjacent string literals normalize to + # the same value. So, we must normalize before any comparisons are + # made. + a = self.clone().finish() + + if isinstance(other, StringExpansion): + if isinstance(a, StringExpansion): + return a == other + + # A normalized Expansion != StringExpansion. + return False + + b = other.clone().finish() + + # b could be a StringExpansion now. + if isinstance(b, StringExpansion): + if isinstance(a, StringExpansion): + return a == b + + # Our normalized Expansion != normalized StringExpansion. + return False + + if len(a) != len(b): + return False + + for i in xrange(len(self)): + e1, is_func1 = a[i] + e2, is_func2 = b[i] + + if is_func1 != is_func2: + return False + + if type(e1) != type(e2): + return False + + if e1 != e2: + return False + + return True + + def __ne__(self, other): + return not self.__eq__(other) + class Variables(object): """ A mapping from variable names to variables. Variables have flavor, source, and value. The value is an @@ -1542,6 +1724,10 @@ class Makefile(object): if len(np.rules): self.context = process.getcontext(1) + flavor, source, value = self.variables.get('.DEFAULT_GOAL') + if value is not None: + self.defaulttarget = value.resolvestr(self, self.variables, ['.DEFAULT_GOAL']).strip() + self.error = False def include(self, path, required=True, weak=False, loc=None): diff --git a/build/pymake/pymake/functions.py b/build/pymake/pymake/functions.py index 5d12ecf4cb6e..d27fdd359661 100644 --- a/build/pymake/pymake/functions.py +++ b/build/pymake/pymake/functions.py @@ -9,6 +9,21 @@ from cStringIO import StringIO log = logging.getLogger('pymake.data') +def emit_expansions(descend, *expansions): + """Helper function to emit all expansions within an input set.""" + for expansion in expansions: + yield expansion + + if not descend or not isinstance(expansion, list): + continue + + for e, is_func in expansion: + if is_func: + for exp in e.expansions(True): + yield exp + else: + yield e + class Function(object): """ An object that represents a function call. This class is always subclassed @@ -44,6 +59,60 @@ class Function(object): assert isinstance(arg, (data.Expansion, data.StringExpansion)) self._arguments.append(arg) + def to_source(self): + """Convert the function back to make file "source" code.""" + if not hasattr(self, 'name'): + raise Exception("%s must implement to_source()." % self.__class__) + + # The default implementation simply prints the function name and all + # the arguments joined by a comma. + # According to the GNU make manual Section 8.1, whitespace around + # arguments is *not* part of the argument's value. So, we trim excess + # white space so we have consistent behavior. + args = [] + curly = False + for i, arg in enumerate(self._arguments): + arg = arg.to_source() + + if i == 0: + arg = arg.lstrip() + + # Are balanced parens even OK? + if arg.count('(') != arg.count(')'): + curly = True + + args.append(arg) + + if curly: + return '${%s %s}' % (self.name, ','.join(args)) + + return '$(%s %s)' % (self.name, ','.join(args)) + + def expansions(self, descend=False): + """Obtain all expansions contained within this function. + + By default, only expansions directly part of this function are + returned. If descend is True, we will descend into child expansions and + return all of the composite parts. + + This is a generator for pymake.data.BaseExpansion instances. + """ + # Our default implementation simply returns arguments. More advanced + # functions like variable references may need their own implementation. + return emit_expansions(descend, *self._arguments) + + @property + def is_filesystem_dependent(self): + """Exposes whether this function depends on the filesystem for results. + + If True, the function touches the filesystem as part of evaluation. + + This only tests whether the function itself uses the filesystem. If + this function has arguments that are functions that touch the + filesystem, this will return False. + """ + return False + def __len__(self): return len(self._arguments) @@ -53,14 +122,53 @@ class Function(object): ','.join([repr(a) for a in self._arguments]), ) + def __eq__(self, other): + if not hasattr(self, 'name'): + raise Exception("%s must implement __eq__." % self.__class__) + + if type(self) != type(other): + return False + + if self.name != other.name: + return False + + if len(self._arguments) != len(other._arguments): + return False + + for i in xrange(len(self._arguments)): + # According to the GNU make manual Section 8.1, whitespace around + # arguments is *not* part of the argument's value. So, we do a + # whitespace-agnostic comparison. + if i == 0: + a = self._arguments[i] + a.lstrip() + + b = other._arguments[i] + b.lstrip() + + if a != b: + return False + + continue + + if self._arguments[i] != other._arguments[i]: + return False + + return True + + def __ne__(self, other): + return not self.__eq__(other) + class VariableRef(Function): + AUTOMATIC_VARIABLES = set(['@', '%', '<', '?', '^', '+', '|', '*']) + __slots__ = ('vname', 'loc') def __init__(self, loc, vname): self.loc = loc assert isinstance(vname, (data.Expansion, data.StringExpansion)) self.vname = vname - + def setup(self): assert False, "Shouldn't get here" @@ -76,9 +184,27 @@ class VariableRef(Function): value.resolve(makefile, variables, fd, setting + [vname]) + def to_source(self): + if isinstance(self.vname, data.StringExpansion): + if self.vname.s in self.AUTOMATIC_VARIABLES: + return '$%s' % self.vname.s + + return '$(%s)' % self.vname.s + + return '$(%s)' % self.vname.to_source() + + def expansions(self, descend=False): + return emit_expansions(descend, self.vname) + def __repr__(self): return "VariableRef<%s>(%r)" % (self.loc, self.vname) + def __eq__(self, other): + if not isinstance(other, VariableRef): + return False + + return self.vname == other.vname + class SubstitutionRef(Function): """$(VARNAME:.c=.o) and $(VARNAME:%.c=%.o)""" @@ -114,10 +240,27 @@ class SubstitutionRef(Function): fd.write(' '.join([f.subst(substto, word, False) for word in value.resolvesplit(makefile, variables, setting + [vname])])) + def to_source(self): + return '$(%s:%s=%s)' % ( + self.vname.to_source(), + self.substfrom.to_source(), + self.substto.to_source()) + + def expansions(self, descend=False): + return emit_expansions(descend, self.vname, self.substfrom, + self.substto) + def __repr__(self): return "SubstitutionRef<%s>(%r:%r=%r)" % ( self.loc, self.vname, self.substfrom, self.substto,) + def __eq__(self, other): + if not isinstance(other, SubstitutionRef): + return False + + return self.vname == other.vname and self.substfrom == other.substfrom \ + and self.substto == other.substto + class SubstFunction(Function): name = 'subst' minargs = 3 @@ -352,7 +495,7 @@ class BasenameFunction(Function): util.joiniter(fd, self.basenames(self._arguments[0].resolvesplit(makefile, variables, setting))) class AddSuffixFunction(Function): - name = 'addprefix' + name = 'addsuffix' minargs = 2 maxargs = 2 @@ -364,7 +507,7 @@ class AddSuffixFunction(Function): fd.write(' '.join([w + suffix for w in self._arguments[1].resolvesplit(makefile, variables, setting)])) class AddPrefixFunction(Function): - name = 'addsuffix' + name = 'addprefix' minargs = 2 maxargs = 2 @@ -407,7 +550,9 @@ class WildcardFunction(Function): for p in patterns for x in glob(makefile.workdir, p)])) - __slots__ = Function.__slots__ + @property + def is_filesystem_dependent(self): + return True class RealpathFunction(Function): name = 'realpath' @@ -418,6 +563,9 @@ class RealpathFunction(Function): fd.write(' '.join([os.path.realpath(os.path.join(makefile.workdir, path)).replace('\\', '/') for path in self._arguments[0].resolvesplit(makefile, variables, setting)])) + def is_filesystem_dependent(self): + return True + class AbspathFunction(Function): name = 'abspath' minargs = 1 diff --git a/build/pymake/pymake/parserdata.py b/build/pymake/pymake/parserdata.py index c5dcb6fa14d3..fbbec089e667 100644 --- a/build/pymake/pymake/parserdata.py +++ b/build/pymake/pymake/parserdata.py @@ -102,11 +102,26 @@ class Statement(object): Represents parsed make file syntax. This is an abstract base class. Child classes are expected to implement - `execute()`. + basic methods defined below. """ def execute(self, makefile, context): - raise Exception("Must implement execute() in child classes.") + """Executes this Statement within a make file execution context.""" + raise Exception("%s must implement execute()." % self.__class__) + + def to_source(self): + """Obtain the make file "source" representation of the Statement. + + This converts an individual Statement back to a string that can again + be parsed into this Statement. + """ + raise Exception("%s must implement to_source()." % self.__class__) + + def __eq__(self, other): + raise Exception("%s must implement __eq__." % self.__class__) + + def __ne__(self, other): + return self.__eq__(other) class DummyRule(object): __slots__ = () @@ -172,6 +187,29 @@ class Rule(Statement): def dump(self, fd, indent): print >>fd, "%sRule %s: %s" % (indent, self.targetexp, self.depexp) + def to_source(self): + sep = ':' + + if self.doublecolon: + sep = '::' + + deps = self.depexp.to_source() + if len(deps) > 0 and not deps[0].isspace(): + sep += ' ' + + return '\n%s%s%s' % ( + self.targetexp.to_source(escape_variables=True), + sep, + deps) + + def __eq__(self, other): + if not isinstance(other, Rule): + return False + + return self.targetexp == other.targetexp \ + and self.depexp == other.depexp \ + and self.doublecolon == other.doublecolon + class StaticPatternRule(Statement): """ Static pattern rules are rules which specify multiple targets based on a @@ -227,6 +265,33 @@ class StaticPatternRule(Statement): def dump(self, fd, indent): print >>fd, "%sStaticPatternRule %s: %s: %s" % (indent, self.targetexp, self.patternexp, self.depexp) + def to_source(self): + sep = ':' + + if self.doublecolon: + sep = '::' + + pattern = self.patternexp.to_source() + deps = self.depexp.to_source() + + if len(pattern) > 0 and pattern[0] not in (' ', '\t'): + sep += ' ' + + return '\n%s%s%s:%s' % ( + self.targetexp.to_source(escape_variables=True), + sep, + pattern, + deps) + + def __eq__(self, other): + if not isinstance(other, StaticPatternRule): + return False + + return self.targetexp == other.targetexp \ + and self.patternexp == other.patternexp \ + and self.depexp == other.depexp \ + and self.doublecolon == other.doublecolon + class Command(Statement): """ Commands are things that get executed by a rule. @@ -254,6 +319,23 @@ class Command(Statement): def dump(self, fd, indent): print >>fd, "%sCommand %s" % (indent, self.exp,) + def to_source(self): + # Commands have some interesting quirks when it comes to source + # formatting. First, they can be multi-line. Second, a tab needs to be + # inserted at the beginning of every line. Finally, there might be + # variable references inside the command. This means we need to escape + # variable references inside command strings. Luckily, this is handled + # by the Expansion. + s = self.exp.to_source(escape_variables=True) + + return '\n'.join(['\t%s' % line for line in s.split('\n')]) + + def __eq__(self, other): + if not isinstance(other, Command): + return False + + return self.exp == other.exp + class SetVariable(Statement): """ Represents a variable assignment. @@ -336,6 +418,66 @@ class SetVariable(Statement): def dump(self, fd, indent): print >>fd, "%sSetVariable<%s> %s %s\n%s %r" % (indent, self.valueloc, self.vnameexp, self.token, indent, self.value) + def __eq__(self, other): + if not isinstance(other, SetVariable): + return False + + return self.vnameexp == other.vnameexp \ + and self.token == other.token \ + and self.value == other.value \ + and self.targetexp == other.targetexp \ + and self.source == other.source + + def to_source(self): + chars = [] + for i in xrange(0, len(self.value)): + c = self.value[i] + + # Literal # is escaped in variable assignment otherwise it would be + # a comment. + if c == '#': + # If a backslash precedes this, we need to escape it as well. + if i > 0 and self.value[i-1] == '\\': + chars.append('\\') + + chars.append('\\#') + continue + + chars.append(c) + + value = ''.join(chars) + + prefix = '' + if self.source == data.Variables.SOURCE_OVERRIDE: + prefix = 'override ' + + # SetVariable come in two flavors: simple and target-specific. + + # We handle the target-specific syntax first. + if self.targetexp is not None: + return '%s: %s %s %s' % ( + self.targetexp.to_source(), + self.vnameexp.to_source(), + self.token, + value) + + # The variable could be multi-line or have leading whitespace. For + # regular variable assignment, whitespace after the token but before + # the value is ignored. If we see leading whitespace in the value here, + # the variable must have come from a define. + if value.count('\n') > 0 or (len(value) and value[0].isspace()): + # The parser holds the token in vnameexp for whatever reason. + return '%sdefine %s\n%s\nendef' % ( + prefix, + self.vnameexp.to_source(), + value) + + return '%s%s %s %s' % ( + prefix, + self.vnameexp.to_source(), + self.token, + value) + class Condition(object): """ An abstract "condition", either ifeq or ifdef, perhaps negated. @@ -347,6 +489,12 @@ class Condition(object): def evaluate(self, makefile) """ + def __eq__(self, other): + raise Exception("%s must implement __eq__." % __class__) + + def __ne__(self, other): + return not self.__eq__(other) + class EqCondition(Condition): """ Represents an ifeq or ifneq conditional directive. @@ -375,6 +523,14 @@ class EqCondition(Condition): def __str__(self): return "ifeq (expected=%s) %s %s" % (self.expected, self.exp1, self.exp2) + def __eq__(self, other): + if not isinstance(other, EqCondition): + return False + + return self.exp1 == other.exp1 \ + and self.exp2 == other.exp2 \ + and self.expected == other.expected + class IfdefCondition(Condition): """ Represents an ifdef or ifndef conditional directive. @@ -404,6 +560,12 @@ class IfdefCondition(Condition): def __str__(self): return "ifdef (expected=%s) %s" % (self.expected, self.exp) + def __eq__(self, other): + if not isinstance(other, IfdefCondition): + return False + + return self.exp == other.exp and self.expected == other.expected + class ElseCondition(Condition): """ Represents the transition between branches in a ConditionBlock. @@ -416,6 +578,9 @@ class ElseCondition(Condition): def __str__(self): return "else" + def __eq__(self, other): + return isinstance(other, ElseCondition) + class ConditionBlock(Statement): """ A set of related Conditions. @@ -473,6 +638,106 @@ class ConditionBlock(Statement): print >>fd, "%s ~Condition" % (indent,) print >>fd, "%s~ConditionBlock" % (indent,) + def to_source(self): + lines = [] + index = 0 + for condition, statements in self: + lines.append(ConditionBlock.condition_source(condition, index)) + index += 1 + + for statement in statements: + lines.append(statement.to_source()) + + lines.append('endif') + + return '\n'.join(lines) + + def __eq__(self, other): + if not isinstance(other, ConditionBlock): + return False + + if len(self) != len(other): + return False + + for i in xrange(0, len(self)): + our_condition, our_statements = self[i] + other_condition, other_statements = other[i] + + if our_condition != other_condition: + return False + + if our_statements != other_statements: + return False + + return True + + @staticmethod + def condition_source(statement, index): + """Convert a condition to its source representation. + + The index argument defines the index of this condition inside a + ConditionBlock. If it is greater than 0, an "else" will be prepended + to the result, if necessary. + """ + prefix = '' + if isinstance(statement, (EqCondition, IfdefCondition)) and index > 0: + prefix = 'else ' + + if isinstance(statement, IfdefCondition): + s = statement.exp.s + + if statement.expected: + return '%sifdef %s' % (prefix, s) + + return '%sifndef %s' % (prefix, s) + + if isinstance(statement, EqCondition): + args = [ + statement.exp1.to_source(escape_comments=True), + statement.exp2.to_source(escape_comments=True)] + + use_quotes = False + single_quote_present = False + double_quote_present = False + for i, arg in enumerate(args): + if len(arg) > 0 and (arg[0].isspace() or arg[-1].isspace()): + use_quotes = True + + if "'" in arg: + single_quote_present = True + + if '"' in arg: + double_quote_present = True + + # Quote everything if needed. + if single_quote_present and double_quote_present: + raise Exception('Cannot format condition with multiple quotes.') + + if use_quotes: + for i, arg in enumerate(args): + # Double to single quotes. + if single_quote_present: + args[i] = '"' + arg + '"' + else: + args[i] = "'" + arg + "'" + + body = None + if use_quotes: + body = ' '.join(args) + else: + body = '(%s)' % ','.join(args) + + if statement.expected: + return '%sifeq %s' % (prefix, body) + + return '%sifneq %s' % (prefix, body) + + if isinstance(statement, ElseCondition): + return 'else' + + raise Exception('Unhandled Condition statement: %s' % + statement.__class__) + def __iter__(self): return iter(self._groups) @@ -508,6 +773,20 @@ class Include(Statement): def dump(self, fd, indent): print >>fd, "%sInclude %s" % (indent, self.exp) + def to_source(self): + prefix = '' + + if not self.required: + prefix = '-' + + return '%sinclude %s' % (prefix, self.exp.to_source()) + + def __eq__(self, other): + if not isinstance(other, Include): + return False + + return self.exp == other.exp and self.required == other.required + class VPathDirective(Statement): """ Represents the vpath directive. @@ -541,6 +820,15 @@ class VPathDirective(Statement): def dump(self, fd, indent): print >>fd, "%sVPath %s" % (indent, self.exp) + def to_source(self): + return 'vpath %s' % self.exp.to_source() + + def __eq__(self, other): + if not isinstance(other, VPathDirective): + return False + + return self.exp == other.exp + class ExportDirective(Statement): """ Represents the "export" directive. @@ -577,6 +865,17 @@ class ExportDirective(Statement): def dump(self, fd, indent): print >>fd, "%sExport (single=%s) %s" % (indent, self.single, self.exp) + def to_source(self): + return ('export %s' % self.exp.to_source()).rstrip() + + def __eq__(self, other): + if not isinstance(other, ExportDirective): + return False + + # single is irrelevant because it just says whether the next Statement + # contains a variable definition. + return self.exp == other.exp + class UnexportDirective(Statement): """ Represents the "unexport" directive. @@ -596,6 +895,15 @@ class UnexportDirective(Statement): def dump(self, fd, indent): print >>fd, "%sUnexport %s" % (indent, self.exp) + def to_source(self): + return 'unexport %s' % self.exp.to_source() + + def __eq__(self, other): + if not isinstance(other, UnexportDirective): + return False + + return self.exp == other.exp + class EmptyDirective(Statement): """ Represents a standalone statement, usually an Expansion. @@ -619,6 +927,15 @@ class EmptyDirective(Statement): def dump(self, fd, indent): print >>fd, "%sEmptyDirective: %s" % (indent, self.exp) + def to_source(self): + return self.exp.to_source() + + def __eq__(self, other): + if not isinstance(other, EmptyDirective): + return False + + return self.exp == other.exp + class _EvalContext(object): __slots__ = ('currule', 'weak') @@ -656,6 +973,9 @@ class StatementList(list): self.dump(fd, '') return fd.getvalue() + def to_source(self): + return '\n'.join([s.to_source() for s in self]) + def iterstatements(stmts): for s in stmts: yield s diff --git a/build/pymake/tests/datatests.py b/build/pymake/tests/datatests.py index 3ccc6b33c69f..513028b0b2e8 100644 --- a/build/pymake/tests/datatests.py +++ b/build/pymake/tests/datatests.py @@ -1,4 +1,4 @@ -import pymake.data, pymake.util +import pymake.data, pymake.functions, pymake.util import unittest import re from cStringIO import StringIO @@ -74,5 +74,164 @@ class LRUTest(unittest.TestCase): self.assertEqual(goti, di, "debugitems, iteration %i, got %r expected %r" % (i, goti, di)) +class EqualityTest(unittest.TestCase): + def test_string_expansion(self): + s1 = pymake.data.StringExpansion('foo bar', None) + s2 = pymake.data.StringExpansion('foo bar', None) + + self.assertEqual(s1, s2) + + def test_expansion_simple(self): + s1 = pymake.data.Expansion(None) + s2 = pymake.data.Expansion(None) + + self.assertEqual(s1, s2) + + s1.appendstr('foo') + s2.appendstr('foo') + self.assertEqual(s1, s2) + + def test_expansion_string_finish(self): + """Adjacent strings should normalize to same value.""" + s1 = pymake.data.Expansion(None) + s2 = pymake.data.Expansion(None) + + s1.appendstr('foo') + s2.appendstr('foo') + + s1.appendstr(' bar') + s1.appendstr(' baz') + s2.appendstr(' bar baz') + + self.assertEqual(s1, s2) + + def test_function(self): + s1 = pymake.data.Expansion(None) + s2 = pymake.data.Expansion(None) + + n1 = pymake.data.StringExpansion('FOO', None) + n2 = pymake.data.StringExpansion('FOO', None) + + v1 = pymake.functions.VariableRef(None, n1) + v2 = pymake.functions.VariableRef(None, n2) + + s1.appendfunc(v1) + s2.appendfunc(v2) + + self.assertEqual(s1, s2) + + +class StringExpansionTest(unittest.TestCase): + def test_base_expansion_interface(self): + s1 = pymake.data.StringExpansion('FOO', None) + + self.assertTrue(s1.is_static_string) + + funcs = list(s1.functions()) + self.assertEqual(len(funcs), 0) + + funcs = list(s1.functions(True)) + self.assertEqual(len(funcs), 0) + + refs = list(s1.variable_references()) + self.assertEqual(len(refs), 0) + + +class ExpansionTest(unittest.TestCase): + def test_is_static_string(self): + e1 = pymake.data.Expansion() + e1.appendstr('foo') + + self.assertTrue(e1.is_static_string) + + e1.appendstr('bar') + self.assertTrue(e1.is_static_string) + + vname = pymake.data.StringExpansion('FOO', None) + func = pymake.functions.VariableRef(None, vname) + + e1.appendfunc(func) + + self.assertFalse(e1.is_static_string) + + def test_get_functions(self): + e1 = pymake.data.Expansion() + e1.appendstr('foo') + + vname1 = pymake.data.StringExpansion('FOO', None) + vname2 = pymake.data.StringExpansion('BAR', None) + + func1 = pymake.functions.VariableRef(None, vname1) + func2 = pymake.functions.VariableRef(None, vname2) + + e1.appendfunc(func1) + e1.appendfunc(func2) + + funcs = list(e1.functions()) + self.assertEqual(len(funcs), 2) + + func3 = pymake.functions.SortFunction(None) + func3.append(vname1) + + e1.appendfunc(func3) + + funcs = list(e1.functions()) + self.assertEqual(len(funcs), 3) + + refs = list(e1.variable_references()) + self.assertEqual(len(refs), 2) + + def test_get_functions_descend(self): + e1 = pymake.data.Expansion() + vname1 = pymake.data.StringExpansion('FOO', None) + func1 = pymake.functions.VariableRef(None, vname1) + e2 = pymake.data.Expansion() + e2.appendfunc(func1) + + func2 = pymake.functions.SortFunction(None) + func2.append(e2) + + e1.appendfunc(func2) + + funcs = list(e1.functions()) + self.assertEqual(len(funcs), 1) + + funcs = list(e1.functions(True)) + self.assertEqual(len(funcs), 2) + + self.assertTrue(isinstance(funcs[0], pymake.functions.SortFunction)) + + def test_is_filesystem_dependent(self): + e = pymake.data.Expansion() + vname1 = pymake.data.StringExpansion('FOO', None) + func1 = pymake.functions.VariableRef(None, vname1) + e.appendfunc(func1) + + self.assertFalse(e.is_filesystem_dependent) + + func2 = pymake.functions.WildcardFunction(None) + func2.append(vname1) + e.appendfunc(func2) + + self.assertTrue(e.is_filesystem_dependent) + + def test_is_filesystem_dependent_descend(self): + sort = pymake.functions.SortFunction(None) + wildcard = pymake.functions.WildcardFunction(None) + + e = pymake.data.StringExpansion('foo/*', None) + wildcard.append(e) + + e = pymake.data.Expansion(None) + e.appendfunc(wildcard) + + sort.append(e) + + e = pymake.data.Expansion(None) + e.appendfunc(sort) + + self.assertTrue(e.is_filesystem_dependent) + + if __name__ == '__main__': unittest.main() diff --git a/build/pymake/tests/default-goal.mk b/build/pymake/tests/default-goal.mk new file mode 100644 index 000000000000..693ff6c344a5 --- /dev/null +++ b/build/pymake/tests/default-goal.mk @@ -0,0 +1,7 @@ +not-default: + @echo TEST-FAIL + +default: + @echo TEST-PASS + +.DEFAULT_GOAL := default diff --git a/build/pymake/tests/formattingtests.py b/build/pymake/tests/formattingtests.py new file mode 100644 index 000000000000..7aad6d4cc177 --- /dev/null +++ b/build/pymake/tests/formattingtests.py @@ -0,0 +1,289 @@ +# This file contains test code for the formatting of parsed statements back to +# make file "source." It essentially verifies to to_source() functions +# scattered across the tree. + +import glob +import logging +import os.path +import unittest + +from pymake.data import Expansion +from pymake.data import StringExpansion +from pymake.functions import BasenameFunction +from pymake.functions import SubstitutionRef +from pymake.functions import VariableRef +from pymake.functions import WordlistFunction +from pymake.parserdata import Include +from pymake.parserdata import SetVariable +from pymake.parser import parsestring +from pymake.parser import SyntaxError + +class TestBase(unittest.TestCase): + pass + +class VariableRefTest(TestBase): + def test_string_name(self): + e = StringExpansion('foo', None) + v = VariableRef(None, e) + + self.assertEqual(v.to_source(), '$(foo)') + + def test_special_variable(self): + e = StringExpansion('<', None) + v = VariableRef(None, e) + + self.assertEqual(v.to_source(), '$<') + + def test_expansion_simple(self): + e = Expansion() + e.appendstr('foo') + e.appendstr('bar') + + v = VariableRef(None, e) + + self.assertEqual(v.to_source(), '$(foobar)') + +class StandardFunctionTest(TestBase): + def test_basename(self): + e1 = StringExpansion('foo', None) + v = VariableRef(None, e1) + e2 = Expansion(None) + e2.appendfunc(v) + + b = BasenameFunction(None) + b.append(e2) + + self.assertEqual(b.to_source(), '$(basename $(foo))') + + def test_wordlist(self): + e1 = StringExpansion('foo', None) + e2 = StringExpansion('bar ', None) + e3 = StringExpansion(' baz', None) + + w = WordlistFunction(None) + w.append(e1) + w.append(e2) + w.append(e3) + + self.assertEqual(w.to_source(), '$(wordlist foo,bar , baz)') + + def test_curly_brackets(self): + e1 = Expansion(None) + e1.appendstr('foo') + + e2 = Expansion(None) + e2.appendstr('foo ( bar') + + f = WordlistFunction(None) + f.append(e1) + f.append(e2) + + self.assertEqual(f.to_source(), '${wordlist foo,foo ( bar}') + +class StringExpansionTest(TestBase): + def test_simple(self): + e = StringExpansion('foobar', None) + self.assertEqual(e.to_source(), 'foobar') + + e = StringExpansion('$var', None) + self.assertEqual(e.to_source(), '$var') + + def test_escaping(self): + e = StringExpansion('$var', None) + self.assertEqual(e.to_source(escape_variables=True), '$$var') + + e = StringExpansion('this is # not a comment', None) + self.assertEqual(e.to_source(escape_comments=True), + 'this is \# not a comment') + + def test_empty(self): + e = StringExpansion('', None) + self.assertEqual(e.to_source(), '') + + e = StringExpansion(' ', None) + self.assertEqual(e.to_source(), ' ') + +class ExpansionTest(TestBase): + def test_single_string(self): + e = Expansion() + e.appendstr('foo') + + self.assertEqual(e.to_source(), 'foo') + + def test_multiple_strings(self): + e = Expansion() + e.appendstr('hello') + e.appendstr('world') + + self.assertEqual(e.to_source(), 'helloworld') + + def test_string_escape(self): + e = Expansion() + e.appendstr('$var') + self.assertEqual(e.to_source(), '$var') + self.assertEqual(e.to_source(escape_variables=True), '$$var') + + e = Expansion() + e.appendstr('foo') + e.appendstr(' $bar') + self.assertEqual(e.to_source(escape_variables=True), 'foo $$bar') + +class SubstitutionRefTest(TestBase): + def test_simple(self): + name = StringExpansion('foo', None) + c = StringExpansion('%.c', None) + o = StringExpansion('%.o', None) + s = SubstitutionRef(None, name, c, o) + + self.assertEqual(s.to_source(), '$(foo:%.c=%.o)') + +class SetVariableTest(TestBase): + def test_simple(self): + v = SetVariable(StringExpansion('foo', None), '=', 'bar', None, None) + self.assertEqual(v.to_source(), 'foo = bar') + + def test_multiline(self): + s = 'hello\nworld' + foo = StringExpansion('FOO', None) + + v = SetVariable(foo, '=', s, None, None) + + self.assertEqual(v.to_source(), 'define FOO\nhello\nworld\nendef') + + def test_multiline_immediate(self): + source = 'define FOO :=\nhello\nworld\nendef' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), source) + + def test_target_specific(self): + foo = StringExpansion('FOO', None) + bar = StringExpansion('BAR', None) + + v = SetVariable(foo, '+=', 'value', None, bar) + + self.assertEqual(v.to_source(), 'BAR: FOO += value') + +class IncludeTest(TestBase): + def test_include(self): + e = StringExpansion('rules.mk', None) + i = Include(e, True, False) + self.assertEqual(i.to_source(), 'include rules.mk') + + i = Include(e, False, False) + self.assertEqual(i.to_source(), '-include rules.mk') + +class IfdefTest(TestBase): + def test_simple(self): + source = 'ifdef FOO\nbar := $(value)\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements[0].to_source(), source) + + def test_nested(self): + source = 'ifdef FOO\nifdef BAR\nhello = world\nendif\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements[0].to_source(), source) + + def test_negation(self): + source = 'ifndef FOO\nbar += value\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements[0].to_source(), source) + +class IfeqTest(TestBase): + def test_simple(self): + source = 'ifeq ($(foo),bar)\nhello = $(world)\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements[0].to_source(), source) + + def test_negation(self): + source = 'ifneq (foo,bar)\nhello = world\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), source) + +class ConditionBlocksTest(TestBase): + def test_mixed_conditions(self): + source = 'ifdef FOO\nifeq ($(FOO),bar)\nvar += $(value)\nendif\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), source) + + def test_extra_statements(self): + source = 'ifdef FOO\nF := 1\nifdef BAR\nB += 1\nendif\nC = 1\nendif' + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), source) + + def test_whitespace_preservation(self): + source = "ifeq ' x' 'x '\n$(error stripping)\nendif" + + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), source) + + source = 'ifneq (x , x)\n$(error stripping)\nendif' + statements = parsestring(source, 'foo.mk') + self.assertEqual(statements.to_source(), + 'ifneq (x,x)\n$(error stripping)\nendif') + +class MakefileCorupusTest(TestBase): + """Runs the make files from the pymake corpus through the formatter. + + All the above tests are child's play compared to this. + """ + + # Our reformatting isn't perfect. We ignore files with known failures until + # we make them work. + # TODO Address these formatting corner cases. + _IGNORE_FILES = [ + # We are thrown off by backslashes at end of lines. + 'comment-parsing.mk', + 'escape-chars.mk', + 'include-notfound.mk', + ] + + def _get_test_files(self): + ourdir = os.path.dirname(os.path.abspath(__file__)) + + for makefile in glob.glob(os.path.join(ourdir, '*.mk')): + if os.path.basename(makefile) in self._IGNORE_FILES: + continue + + source = None + with open(makefile, 'rU') as fh: + source = fh.read() + + try: + yield (makefile, source, parsestring(source, makefile)) + except SyntaxError: + continue + + def test_reparse_consistency(self): + for filename, source, statements in self._get_test_files(): + reformatted = statements.to_source() + + # We should be able to parse the reformatted source fine. + new_statements = parsestring(reformatted, filename) + + # If we do the formatting again, the representation shouldn't + # change. i.e. the only lossy change should be the original + # (whitespace and some semantics aren't preserved). + reformatted_again = new_statements.to_source() + self.assertEqual(reformatted, reformatted_again, + '%s has lossless reformat.' % filename) + + self.assertEqual(len(statements), len(new_statements)) + + for i in xrange(0, len(statements)): + original = statements[i] + formatted = new_statements[i] + + self.assertEqual(original, formatted, '%s %d: %s != %s' % (filename, + i, original, formatted)) + +if __name__ == '__main__': + logging.basicConfig(level=logging.DEBUG) + unittest.main() diff --git a/build/pymake/tests/functiontests.py b/build/pymake/tests/functiontests.py new file mode 100644 index 000000000000..43a344a05990 --- /dev/null +++ b/build/pymake/tests/functiontests.py @@ -0,0 +1,54 @@ +import unittest + +import pymake.data +import pymake.functions + +class VariableRefTest(unittest.TestCase): + def test_get_expansions(self): + e = pymake.data.StringExpansion('FOO', None) + f = pymake.functions.VariableRef(None, e) + + exps = list(f.expansions()) + self.assertEqual(len(exps), 1) + +class GetExpansionsTest(unittest.TestCase): + def test_get_arguments(self): + f = pymake.functions.SubstFunction(None) + + e1 = pymake.data.StringExpansion('FOO', None) + e2 = pymake.data.StringExpansion('BAR', None) + e3 = pymake.data.StringExpansion('BAZ', None) + + f.append(e1) + f.append(e2) + f.append(e3) + + exps = list(f.expansions()) + self.assertEqual(len(exps), 3) + + def test_descend(self): + f = pymake.functions.StripFunction(None) + + e = pymake.data.Expansion(None) + + e1 = pymake.data.StringExpansion('FOO', None) + f1 = pymake.functions.VariableRef(None, e1) + e.appendfunc(f1) + + f2 = pymake.functions.WildcardFunction(None) + e2 = pymake.data.StringExpansion('foo/*', None) + f2.append(e2) + e.appendfunc(f2) + + f.append(e) + + exps = list(f.expansions()) + self.assertEqual(len(exps), 1) + + exps = list(f.expansions(True)) + self.assertEqual(len(exps), 3) + + self.assertFalse(f.is_filesystem_dependent) + +if __name__ == '__main__': + unittest.main() diff --git a/build/tests/unit-ConfigStatus.py b/build/tests/unit-ConfigStatus.py index 26e5c3c533fe..951876a14353 100644 --- a/build/tests/unit-ConfigStatus.py +++ b/build/tests/unit-ConfigStatus.py @@ -54,20 +54,30 @@ class TestFileAvoidWrite(unittest.TestCase): class TestEnvironment(unittest.TestCase): def test_auto_substs(self): - '''Test the automatically set values of ACDEFINES and ALLDEFINES. + '''Test the automatically set values of ACDEFINES, ALLDEFINES + and ALLSUBSTS. ''' env = ConfigEnvironment( defines = [ ('foo', 'bar'), ('baz', 'qux 42'), ('abc', 'def'), ('extra', 'foobar') ], - non_global_defines = ['extra', 'ignore']) + non_global_defines = ['extra', 'ignore'], + substs = [ ('FOO', 'bar'), ('ABC', 'def'), + ('bar', 'baz qux'), ('zzz', '"abc def"') ]) # non_global_defines should be filtered out in ACDEFINES and # ALLDEFINES. # Original order of the defines need to be respected in ACDEFINES - self.assertEqual(env.substs['ACDEFINES'], '-Dfoo=bar -Dbaz=qux\\ 42 -Dabc=def') + self.assertEqual(env.substs['ACDEFINES'], '''-Dfoo=bar -Dbaz=qux\ 42 -Dabc=def''') # ALLDEFINES, on the other hand, needs to be sorted self.assertEqual(env.substs['ALLDEFINES'], '''#define abc def #define baz qux 42 #define foo bar''') + # Likewise for ALLSUBSTS, which also mustn't contain ALLDEFINES + # but contain ACDEFINES + self.assertEqual(env.substs['ALLSUBSTS'], '''ABC = def +ACDEFINES = -Dfoo=bar -Dbaz=qux\ 42 -Dabc=def +FOO = bar +bar = baz qux +zzz = "abc def"''') def test_config_file(self): '''Test the creation of config files. diff --git a/build/win32/mozconfig.vs2010 b/build/win32/mozconfig.vs2010 index 8739895a1ba2..ac644796cbc8 100644 --- a/build/win32/mozconfig.vs2010 +++ b/build/win32/mozconfig.vs2010 @@ -4,9 +4,10 @@ export LIB=/d/msvs10/vc/lib:/d/msvs10/vc/atlmfc/lib:/d/sdks/v7.0/lib:/d/msvs8/VC export PATH="/d/msvs10/VSTSDB/Deploy:/d/msvs10/Common7/IDE/:/d/msvs10/VC/BIN:/d/msvs10/Common7/Tools:/d/msvs10/VC/VCPackages:${PATH}" export WIN32_REDIST_DIR=/d/msvs10/VC/redist/x86/Microsoft.VC100.CRT +. $topsrcdir/build/mozconfig.vs2010-common -mk_add_options "export LIB=$LIB" -mk_add_options "export LIBPATH=$LIBPATH" -mk_add_options "export PATH=$PATH" -mk_add_options "export INCLUDE=$INCLUDE" -mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR" +mk_export_correct_style LIB +mk_export_correct_style LIBPATH +mk_export_correct_style PATH +mk_export_correct_style INCLUDE +mk_export_correct_style WIN32_REDIST_DIR diff --git a/build/win32/mozconfig.vs2010-win64 b/build/win32/mozconfig.vs2010-win64 index 56b59c141e78..a9156a28aac2 100644 --- a/build/win32/mozconfig.vs2010-win64 +++ b/build/win32/mozconfig.vs2010-win64 @@ -5,9 +5,12 @@ export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x86/Microsoft.VC100.CRT export MOZ_TOOLS=C:/mozilla-build/moztools export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:/c/mozilla-build/moztools:/c/Tools/sdks/v7.0/bin:${PATH}" -mk_add_options "export LIB=$LIB" -mk_add_options "export LIBPATH=$LIBPATH" -mk_add_options "export PATH=$PATH" -mk_add_options "export INCLUDE=$INCLUDE" -mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR" +. $topsrcdir/build/mozconfig.vs2010-common + +mk_export_correct_style LIB +mk_export_correct_style LIBPATH +mk_export_correct_style PATH +mk_export_correct_style INCLUDE +mk_export_correct_style WIN32_REDIST_DIR + mk_add_options "export MOZ_TOOLS=$MOZ_TOOLS" diff --git a/build/win64/mozconfig.vs2010 b/build/win64/mozconfig.vs2010 index 4dc92e8523c3..43ebe921b655 100644 --- a/build/win64/mozconfig.vs2010 +++ b/build/win64/mozconfig.vs2010 @@ -8,9 +8,10 @@ export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x64/Microsoft.VC100.CRT # https://connect.microsoft.com/VisualStudio/feedback/details/686117/ export LD=/c/tools/msvs10/VC/BIN/x86_amd64/link.exe +. $topsrcdir/build/mozconfig.vs2010-common -mk_add_options "export LIB=$LIB" -mk_add_options "export LIBPATH=$LIBPATH" -mk_add_options "export PATH=$PATH" -mk_add_options "export INCLUDE=$INCLUDE" -mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR" +mk_export_correct_style LIB +mk_export_correct_style LIBPATH +mk_export_correct_style PATH +mk_export_correct_style INCLUDE +mk_export_correct_style WIN32_REDIST_DIR diff --git a/client.mk b/client.mk index 1ba3cac8f723..57937e921e3c 100644 --- a/client.mk +++ b/client.mk @@ -103,7 +103,7 @@ endef # As $(shell) doesn't preserve newlines, use sed to replace them with an # unlikely sequence (||), which is then replaced back to newlines by make # before evaluation. -$(eval $(subst ||,$(CR),$(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) 2> $(TOPSRCDIR)/.mozconfig.out | sed 's/$$/||/'))) +$(eval $(subst ||,$(CR),$(shell _PYMAKE=$(.PYMAKE) $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) 2> $(TOPSRCDIR)/.mozconfig.out | sed 's/$$/||/'))) ifndef MOZ_OBJDIR MOZ_OBJDIR = obj-$(CONFIG_GUESS) @@ -402,7 +402,20 @@ cleansrcdir: build/autoconf/clean-config.sh; \ fi; -## Sanity check $X and js/src/$X are in sync +# Because SpiderMonkey can be distributed and built independently +# of the Mozilla source tree, it contains its own copies of many of +# the files used by the top-level Mozilla build process, from the +# 'config' and 'build' subtrees. +# +# To make it simpler to keep the copies in sync, we follow the policy +# that the SpiderMonkey copies must always be exact copies of those in +# the containing Mozilla tree. If you've made a change in one, it +# belongs in the other as well. If the change isn't right for both +# places, then that's something to bring up with the other developers. +# +# Some files are reasonable to diverge; for example, +# js/src/config/autoconf.mk.in doesn't need most of the stuff in +# config/autoconf.mk.in. .PHONY: check-sync-dirs check-sync-dirs: check-sync-dirs-build check-sync-dirs-config check-sync-dirs-%: diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 58da2dd4d7b6..3a1f0d8f49e1 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -1,668 +1,2 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# A netscape style .mk file for autoconf builds - -target = @target@ -ac_configure_args = @ac_configure_args@ -MOZILLA_VERSION = @MOZILLA_VERSION@ -FIREFOX_VERSION = @FIREFOX_VERSION@ - -MOZ_BUILD_APP = @MOZ_BUILD_APP@ -MOZ_APP_NAME = @MOZ_APP_NAME@ -MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@ -MOZ_APP_BASENAME = @MOZ_APP_BASENAME@ -MOZ_APP_VENDOR = @MOZ_APP_VENDOR@ -MOZ_APP_PROFILE = @MOZ_APP_PROFILE@ -MOZ_APP_ID = @MOZ_APP_ID@ -MAR_CHANNEL_ID = @MAR_CHANNEL_ID@ -ACCEPTED_MAR_CHANNEL_IDS = @ACCEPTED_MAR_CHANNEL_IDS@ -MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@ -MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@ -MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@ -MOZ_UA_OS_AGNOSTIC = @MOZ_UA_OS_AGNOSTIC@ -MOZ_APP_VERSION = @MOZ_APP_VERSION@ -MOZ_APP_MAXVERSION = @MOZ_APP_MAXVERSION@ -MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@ -MOZ_MACBUNDLE_ID = @MOZ_MACBUNDLE_ID@ -MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@ - -MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -includedir = @includedir@ -libdir = @libdir@ -datadir = @datadir@ -mandir = @mandir@ - -LIBXUL_SDK = @LIBXUL_SDK@ - -MOZ_FS_LAYOUT = @MOZ_FS_LAYOUT@ - -L10NBASEDIR = @L10NBASEDIR@ - -LIBXUL_DIST = @LIBXUL_DIST@ -SYSTEM_LIBXUL = @SYSTEM_LIBXUL@ - -XULRUNNER_STUB_NAME = @XULRUNNER_STUB_NAME@ - -MOZ_CHROME_FILE_FORMAT = @MOZ_CHROME_FILE_FORMAT@ -MOZ_OMNIJAR = @MOZ_OMNIJAR@ -OMNIJAR_NAME = @OMNIJAR_NAME@ - -MOZ_WIDGET_TOOLKIT = @MOZ_WIDGET_TOOLKIT@ -MOZ_GFX_OPTIMIZE_MOBILE = @MOZ_GFX_OPTIMIZE_MOBILE@ - -MOZ_X11 = @MOZ_X11@ - -MOZ_PANGO = @MOZ_PANGO@ - -MOZ_JS_LIBS = @MOZ_JS_LIBS@ - -MOZ_DEBUG = @MOZ_DEBUG@ -MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@ -MOZ_DEBUG_ENABLE_DEFS = @MOZ_DEBUG_ENABLE_DEFS@ -MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@ -MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@ -MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@ -MOZ_EXTENSIONS = @MOZ_EXTENSIONS@ -MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@ -MOZ_IPDL_TESTS = @MOZ_IPDL_TESTS@ -MOZ_MEMORY = @MOZ_MEMORY@ -MOZ_JEMALLOC = @MOZ_JEMALLOC@ -MOZ_PROFILING = @MOZ_PROFILING@ -MOZ_ENABLE_PROFILER_SPS = @MOZ_ENABLE_PROFILER_SPS@ -MOZ_JPROF = @MOZ_JPROF@ -MOZ_SHARK = @MOZ_SHARK@ -MOZ_CALLGRIND = @MOZ_CALLGRIND@ -MOZ_VALGRIND = @MOZ_VALGRIND@ -MOZ_VTUNE = @MOZ_VTUNE@ -MOZ_ETW = @MOZ_ETW@ -DEHYDRA_PATH = @DEHYDRA_PATH@ - -MOZ_USING_CCACHE = @MOZ_USING_CCACHE@ -CLANG_CXX = @CLANG_CXX@ -MOZ_LINKER = @MOZ_LINKER@ -MOZ_OLD_LINKER = @MOZ_OLD_LINKER@ -MOZ_ENABLE_SZIP = @MOZ_ENABLE_SZIP@ -NS_TRACE_MALLOC = @NS_TRACE_MALLOC@ -USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@ -USE_ELF_HACK = @USE_ELF_HACK@ -STDCXX_COMPAT = @STDCXX_COMPAT@ -MOZ_LIBSTDCXX_TARGET_VERSION=@MOZ_LIBSTDCXX_TARGET_VERSION@ -MOZ_LIBSTDCXX_HOST_VERSION=@MOZ_LIBSTDCXX_HOST_VERSION@ -INCREMENTAL_LINKER = @INCREMENTAL_LINKER@ -MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@ -ENABLE_TESTS = @ENABLE_TESTS@ -ENABLE_MARIONETTE = @ENABLE_MARIONETTE@ -IBMBIDI = @IBMBIDI@ -MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHARDET@ -ACCESSIBILITY = @ACCESSIBILITY@ -MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@ -MOZ_MAINTENANCE_SERVICE = @MOZ_MAINTENANCE_SERVICE@ -MOZ_VERIFY_MAR_SIGNATURE = @MOZ_VERIFY_MAR_SIGNATURE@ -MOZ_ENABLE_SIGNMAR = @MOZ_ENABLE_SIGNMAR@ -MOZ_UPDATER = @MOZ_UPDATER@ -MOZ_UPDATE_CHANNEL = @MOZ_UPDATE_CHANNEL@ -MOZ_UPDATE_PACKAGING = @MOZ_UPDATE_PACKAGING@ -MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@ -NS_ENABLE_TSF = @NS_ENABLE_TSF@ -MOZ_SPELLCHECK = @MOZ_SPELLCHECK@ -MOZ_ANDROID_HISTORY = @MOZ_ANDROID_HISTORY@ -MOZ_WEBSMS_BACKEND = @MOZ_WEBSMS_BACKEND@ -MOZ_JAVA_COMPOSITOR = @MOZ_JAVA_COMPOSITOR@ -MOZ_ONLY_TOUCH_EVENTS = @MOZ_ONLY_TOUCH_EVENTS@ -MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@ -MOZ_FEEDS = @MOZ_FEEDS@ -MOZ_TOOLKIT_SEARCH = @MOZ_TOOLKIT_SEARCH@ -MOZ_PLACES = @MOZ_PLACES@ -MOZ_SAFE_BROWSING = @MOZ_SAFE_BROWSING@ -MOZ_URL_CLASSIFIER = @MOZ_URL_CLASSIFIER@ -MOZ_ZIPWRITER = @MOZ_ZIPWRITER@ -MOZ_OGG = @MOZ_OGG@ -MOZ_RAW = @MOZ_RAW@ -MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@ -MOZ_SPEEX_RESAMPLER = @MOZ_SPEEX_RESAMPLER@ -MOZ_CUBEB = @MOZ_CUBEB@ -MOZ_WAVE = @MOZ_WAVE@ -MOZ_MEDIA = @MOZ_MEDIA@ -MOZ_VORBIS = @MOZ_VORBIS@ -MOZ_TREMOR = @MOZ_TREMOR@ -MOZ_OPUS = @MOZ_OPUS@ -MOZ_WEBM = @MOZ_WEBM@ -MOZ_MEDIA_PLUGINS = @MOZ_MEDIA_PLUGINS@ -MOZ_OMX_PLUGIN = @MOZ_OMX_PLUGIN@ -MOZ_GSTREAMER = @MOZ_GSTREAMER@ -MOZ_VP8 = @MOZ_VP8@ -MOZ_VP8_ERROR_CONCEALMENT = @MOZ_VP8_ERROR_CONCEALMENT@ -MOZ_VP8_ENCODER = @MOZ_VP8_ENCODER@ -VPX_AS = @VPX_AS@ -VPX_ASFLAGS = @VPX_ASFLAGS@ -VPX_DASH_C_FLAG = @VPX_DASH_C_FLAG@ -VPX_AS_CONVERSION = @VPX_AS_CONVERSION@ -VPX_ASM_SUFFIX = @VPX_ASM_SUFFIX@ -VPX_X86_ASM = @VPX_X86_ASM@ -VPX_ARM_ASM = @VPX_ARM_ASM@ -VPX_NEED_OBJ_INT_EXTRACT = @VPX_NEED_OBJ_INT_EXTRACT@ -LIBJPEG_TURBO_AS = @LIBJPEG_TURBO_AS@ -LIBJPEG_TURBO_ASFLAGS = @LIBJPEG_TURBO_ASFLAGS@ -LIBJPEG_TURBO_X86_ASM = @LIBJPEG_TURBO_X86_ASM@ -LIBJPEG_TURBO_X64_ASM = @LIBJPEG_TURBO_X64_ASM@ -LIBJPEG_TURBO_ARM_ASM = @LIBJPEG_TURBO_ARM_ASM@ -NS_PRINTING = @NS_PRINTING@ -MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@ -MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@ -MOZ_CRASHREPORTER_INJECTOR = @MOZ_CRASHREPORTER_INJECTOR@ -MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@ -MOC = @MOC@ -RCC = @RCC@ -MOZ_NSS_PATCH = @MOZ_NSS_PATCH@ -MOZ_WEBGL = @MOZ_WEBGL@ -MOZ_ANGLE_RENDERER = @MOZ_ANGLE_RENDERER@ -MOZ_DIRECTX_SDK_PATH = @MOZ_DIRECTX_SDK_PATH@ -MOZ_DIRECTX_SDK_CPU_SUFFIX = @MOZ_DIRECTX_SDK_CPU_SUFFIX@ -MOZ_D3DX9_VERSION = @MOZ_D3DX9_VERSION@ -MOZ_D3DX9_CAB = @MOZ_D3DX9_CAB@ -MOZ_D3DCOMPILER_CAB = @MOZ_D3DCOMPILER_CAB@ -MOZ_D3DX9_DLL = @MOZ_D3DX9_DLL@ -MOZ_D3DCOMPILER_DLL = @MOZ_D3DCOMPILER_DLL@ -MOZ_GL_PROVIDER = @MOZ_GL_PROVIDER@ -MOZ_GL_DEFAULT_PROVIDER = @MOZ_GL_DEFAULT_PROVIDER@ -MOZ_WEBRTC = @MOZ_WEBRTC@ - - -JAVA=@JAVA@ -JAVAC=@JAVAC@ -JAR=@JAR@ - -TAR=@TAR@ - -MAKENSISU=@MAKENSISU@ - -# The MOZ_UI_LOCALE var is used to build a particular locale. Do *not* -# use the var to change any binary files. Do *not* use this var unless you -# write rules for the "clean-locale" and "locale" targets. -MOZ_UI_LOCALE = @MOZ_UI_LOCALE@ - -MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@ -MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@ - -MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@ - -XPCOM_FROZEN_LDOPTS=@XPCOM_FROZEN_LDOPTS@ -XPCOM_LIBS=@XPCOM_LIBS@ -LIBXUL_LIBS=@LIBXUL_LIBS@ - -ENABLE_STRIP = @ENABLE_STRIP@ -PKG_SKIP_STRIP = @PKG_SKIP_STRIP@ -STRIP_FLAGS = @STRIP_FLAGS@ - -MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO_LIB_COMMAND@ -MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@ - -MOZ_BUILD_ROOT = @MOZ_BUILD_ROOT@ - -MOZ_XUL = @MOZ_XUL@ - -NECKO_PROTOCOLS = @NECKO_PROTOCOLS@ -NECKO_COOKIES = @NECKO_COOKIES@ -NECKO_WIFI = @NECKO_WIFI@ -MOZ_AUTH_EXTENSION = @MOZ_AUTH_EXTENSION@ - -MOZ_NATIVE_HUNSPELL = @MOZ_NATIVE_HUNSPELL@ -MOZ_HUNSPELL_LIBS = @MOZ_HUNSPELL_LIBS@ -MOZ_HUNSPELL_CFLAGS = @MOZ_HUNSPELL_CFLAGS@ - -MOZ_NATIVE_LIBEVENT = @MOZ_NATIVE_LIBEVENT@ -MOZ_LIBEVENT_LIBS = @MOZ_LIBEVENT_LIBS@ -MOZ_LIBEVENT_INCLUDES = @MOZ_LIBEVENT_INCLUDES@ - -MOZ_NATIVE_LIBVPX = @MOZ_NATIVE_LIBVPX@ -MOZ_LIBVPX_LIBS = @MOZ_LIBVPX_LIBS@ -MOZ_LIBVPX_CFLAGS = @MOZ_LIBVPX_CFLAGS@ - -MOZ_NATIVE_ZLIB = @MOZ_NATIVE_ZLIB@ -MOZ_NATIVE_BZ2 = @MOZ_NATIVE_BZ2@ -MOZ_NATIVE_JPEG = @MOZ_NATIVE_JPEG@ -MOZ_NATIVE_PNG = @MOZ_NATIVE_PNG@ -MOZ_TREE_CAIRO = @MOZ_TREE_CAIRO@ -MOZ_TREE_PIXMAN = @MOZ_TREE_PIXMAN@ - -MOZ_UPDATE_XTERM = @MOZ_UPDATE_XTERM@ -MOZ_PERMISSIONS = @MOZ_PERMISSIONS@ -MOZ_XTF = @MOZ_XTF@ -MOZ_FLEXBOX = @MOZ_FLEXBOX@ -MOZ_CAIRO_CFLAGS = @MOZ_CAIRO_CFLAGS@ -MOZ_PIXMAN_CFLAGS = @MOZ_PIXMAN_CFLAGS@ - -MOZ_PREF_EXTENSIONS = @MOZ_PREF_EXTENSIONS@ - -MOZ_CAIRO_LIBS = @MOZ_CAIRO_LIBS@ -MOZ_CAIRO_OSLIBS = @MOZ_CAIRO_OSLIBS@ -MOZ_PIXMAN_LIBS = @MOZ_PIXMAN_LIBS@ - -MOZ_ENABLE_GNOMEUI = @MOZ_ENABLE_GNOMEUI@ -MOZ_GNOMEUI_CFLAGS = @MOZ_GNOMEUI_CFLAGS@ -MOZ_GNOMEUI_LIBS = @MOZ_GNOMEUI_LIBS@ - -MOZ_ENABLE_STARTUP_NOTIFICATION = @MOZ_ENABLE_STARTUP_NOTIFICATION@ -MOZ_STARTUP_NOTIFICATION_CFLAGS = @MOZ_STARTUP_NOTIFICATION_CFLAGS@ -MOZ_STARTUP_NOTIFICATION_LIBS = @MOZ_STARTUP_NOTIFICATION_LIBS@ - -MOZ_ENABLE_GNOMEVFS = @MOZ_ENABLE_GNOMEVFS@ -MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@ -MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@ - -MOZ_ENABLE_GCONF = @MOZ_ENABLE_GCONF@ -MOZ_GCONF_CFLAGS = @MOZ_GCONF_CFLAGS@ -MOZ_GCONF_LIBS = @MOZ_GCONF_LIBS@ - -MOZ_ENABLE_GNOME_COMPONENT = @MOZ_ENABLE_GNOME_COMPONENT@ - -MOZ_ENABLE_GIO = @MOZ_ENABLE_GIO@ -MOZ_GIO_CFLAGS = @MOZ_GIO_CFLAGS@ -MOZ_GIO_LIBS = @MOZ_GIO_LIBS@ - -MOZ_NATIVE_NSPR = @MOZ_NATIVE_NSPR@ -MOZ_NATIVE_NSS = @MOZ_NATIVE_NSS@ - -MOZ_B2G_RIL = @MOZ_B2G_RIL@ -MOZ_B2G_BT = @MOZ_B2G_BT@ -MOZ_B2G_CAMERA = @MOZ_B2G_CAMERA@ - -MOZ_SYS_MSG = @MOZ_SYS_MSG@ - -MOZ_ASAN = @MOZ_ASAN@ -MOZ_CFLAGS_NSS = @MOZ_CFLAGS_NSS@ -MOZ_NO_WLZDEFS = @MOZ_NO_WLZDEFS@ - -BUILD_CTYPES = @BUILD_CTYPES@ - -COMPILE_ENVIRONMENT = @COMPILE_ENVIRONMENT@ -CROSS_COMPILE = @CROSS_COMPILE@ - -WCHAR_CFLAGS = @WCHAR_CFLAGS@ - -OS_CPPFLAGS = @OS_CPPFLAGS@ -OS_CFLAGS = @OS_CFLAGS@ -OS_CXXFLAGS = @OS_CXXFLAGS@ -OS_LDFLAGS = @OS_LDFLAGS@ - -OS_COMPILE_CFLAGS = @OS_COMPILE_CFLAGS@ -OS_COMPILE_CXXFLAGS = @OS_COMPILE_CXXFLAGS@ - -OS_LIBS = @OS_LIBS@ -ACDEFINES = @ACDEFINES@ - -WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@ - -MOZ_OPTIMIZE = @MOZ_OPTIMIZE@ -MOZ_FRAMEPTR_FLAGS = @MOZ_FRAMEPTR_FLAGS@ -MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@ -MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@ -MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@ -MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@ - -MOZ_ALLOW_HEAP_EXECUTE_FLAGS = @MOZ_ALLOW_HEAP_EXECUTE_FLAGS@ - -PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@ -PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@ -PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@ -PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@ - -XCFLAGS = @XCFLAGS@ -XLDFLAGS = @XLDFLAGS@ -XLIBS = @XLIBS@ -XEXT_LIBS = @XEXT_LIBS@ -XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@ -XSS_LIBS = @XSS_LIBS@ - -MOZ_THUMB2 = @MOZ_THUMB2@ -MOZ_EGL_XRENDER_COMPOSITE = @MOZ_EGL_XRENDER_COMPOSITE@ - -WIN_TOP_SRC = @WIN_TOP_SRC@ -AR = @AR@ -AR_FLAGS = @AR_FLAGS@ -AR_EXTRACT = @AR_EXTRACT@ -AR_LIST = @AR_LIST@ -AR_DELETE = @AR_DELETE@ -AS = @AS@ -ASFLAGS = @ASFLAGS@ -AS_DASH_C_FLAG = @AS_DASH_C_FLAG@ -LD = @LD@ -RC = @RC@ -RCFLAGS = @RCFLAGS@ -MC = @MC@ -WINDRES = @WINDRES@ -IMPLIB = @IMPLIB@ -FILTER = @FILTER@ -BIN_FLAGS = @BIN_FLAGS@ -MIDL = @MIDL@ -MIDL_FLAGS = @MIDL_FLAGS@ -_MSC_VER = @_MSC_VER@ - -DLL_PREFIX = @DLL_PREFIX@ -LIB_PREFIX = @LIB_PREFIX@ -OBJ_SUFFIX = @OBJ_SUFFIX@ -LIB_SUFFIX = @LIB_SUFFIX@ -DLL_SUFFIX = @DLL_SUFFIX@ -BIN_SUFFIX = @BIN_SUFFIX@ -ASM_SUFFIX = @ASM_SUFFIX@ -IMPORT_LIB_SUFFIX = @IMPORT_LIB_SUFFIX@ -LIBS_DESC_SUFFIX = @LIBS_DESC_SUFFIX@ -USE_N32 = @USE_N32@ -HAVE_64BIT_OS = @HAVE_64BIT_OS@ - -CC = @CC@ -CXX = @CXX@ -CPP = @CPP@ -TOOLCHAIN_PREFIX = @TOOLCHAIN_PREFIX@ - -CC_VERSION = @CC_VERSION@ -CXX_VERSION = @CXX_VERSION@ - -GNU_AS = @GNU_AS@ -GNU_LD = @GNU_LD@ -GNU_CC = @GNU_CC@ -GNU_CXX = @GNU_CXX@ -INTEL_CC = @INTEL_CC@ -INTEL_CXX = @INTEL_CXX@ - -STL_FLAGS = @STL_FLAGS@ -WRAP_STL_INCLUDES = @WRAP_STL_INCLUDES@ -MOZ_MSVC_STL_WRAP__Throw= @MOZ_MSVC_STL_WRAP__Throw@ -MOZ_MSVC_STL_WRAP__RAISE= @MOZ_MSVC_STL_WRAP__RAISE@ - -HOST_CC = @HOST_CC@ -HOST_CXX = @HOST_CXX@ -HOST_CFLAGS = @HOST_CFLAGS@ -HOST_CXXFLAGS = @HOST_CXXFLAGS@ -HOST_LDFLAGS = @HOST_LDFLAGS@ -HOST_OPTIMIZE_FLAGS = @HOST_OPTIMIZE_FLAGS@ -HOST_NSPR_MDCPUCFG = @HOST_NSPR_MDCPUCFG@ -HOST_AR = @HOST_AR@ -HOST_AR_FLAGS = @HOST_AR_FLAGS@ -HOST_LD = @HOST_LD@ -HOST_RANLIB = @HOST_RANLIB@ -HOST_BIN_SUFFIX = @HOST_BIN_SUFFIX@ - -HOST_OS_ARCH = @HOST_OS_ARCH@ -host_cpu = @host_cpu@ -host_vendor = @host_vendor@ -host_os = @host_os@ - -TARGET_NSPR_MDCPUCFG = @TARGET_NSPR_MDCPUCFG@ -TARGET_CPU = @TARGET_CPU@ -TARGET_VENDOR = @TARGET_VENDOR@ -TARGET_OS = @TARGET_OS@ -TARGET_MD_ARCH = @TARGET_MD_ARCH@ -TARGET_XPCOM_ABI = @TARGET_XPCOM_ABI@ - -AUTOCONF = @AUTOCONF@ -GMAKE = @GMAKE@ -PERL = @PERL@ -PYTHON = @PYTHON@ -RANLIB = @RANLIB@ -OBJCOPY = @OBJCOPY@ -UNZIP = @UNZIP@ -ZIP = @ZIP@ -XARGS = @XARGS@ -STRIP = @STRIP@ -DOXYGEN = @DOXYGEN@ -PBBUILD_BIN = @PBBUILD_BIN@ -SDP = @SDP@ -NSINSTALL_BIN = @NSINSTALL_BIN@ -WGET = @WGET@ -RPMBUILD = @RPMBUILD@ - -MOZ_JPEG_CFLAGS = @MOZ_JPEG_CFLAGS@ -MOZ_JPEG_LIBS = @MOZ_JPEG_LIBS@ - -MOZ_ZLIB_CFLAGS = @MOZ_ZLIB_CFLAGS@ -MOZ_ZLIB_LIBS = @MOZ_ZLIB_LIBS@ - -MOZ_BZ2_CFLAGS = @MOZ_BZ2_CFLAGS@ -MOZ_BZ2_LIBS = @MOZ_BZ2_LIBS@ - -MOZ_PNG_CFLAGS = @MOZ_PNG_CFLAGS@ -MOZ_PNG_LIBS = @MOZ_PNG_LIBS@ - -QCMS_LIBS = @QCMS_LIBS@ - -MOZ_HARFBUZZ_LIBS = @MOZ_HARFBUZZ_LIBS@ -MOZ_GRAPHITE_LIBS = @MOZ_GRAPHITE_LIBS@ -MOZ_GRAPHITE = @MOZ_GRAPHITE@ -MOZ_OTS_LIBS = @MOZ_OTS_LIBS@ -MOZ_SKIA_LIBS = @MOZ_SKIA_LIBS@ -MOZ_ENABLE_SKIA = @MOZ_ENABLE_SKIA@ - -MOZ_NATIVE_SQLITE = @MOZ_NATIVE_SQLITE@ -SQLITE_CFLAGS = @SQLITE_CFLAGS@ -SQLITE_LIBS = @SQLITE_LIBS@ - -NSPR_CONFIG = @NSPR_CONFIG@ -NSPR_CFLAGS = @NSPR_CFLAGS@ -NSPR_LIBS = @NSPR_LIBS@ - -NSS_CONFIG = @NSS_CONFIG@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -NSS_DEP_LIBS = @NSS_DEP_LIBS@ -NSS_DISABLE_DBM = @NSS_DISABLE_DBM@ - -XPCOM_GLUE_LDOPTS = @XPCOM_GLUE_LDOPTS@ -XPCOM_STANDALONE_GLUE_LDOPTS = @XPCOM_STANDALONE_GLUE_LDOPTS@ -XPCOM_STATICRUNTIME_GLUE_LDOPTS = @XPCOM_STATICRUNTIME_GLUE_LDOPTS@ -XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS = @XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS@ - -USE_DEPENDENT_LIBS = @USE_DEPENDENT_LIBS@ - -# UNIX98 iconv support -LIBICONV = @LIBICONV@ - -# MKSHLIB_FORCE_ALL is used to force the linker to include all object -# files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker -# to normal behavior. Makefile's that create shared libraries out of -# archives use these flags to force in all of the .o files in the -# archives into the shared library. -WRAP_LDFLAGS = @WRAP_LDFLAGS@ -DSO_CFLAGS = @DSO_CFLAGS@ -DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@ -MKSHLIB = @MKSHLIB@ -MKCSHLIB = @MKCSHLIB@ -MKSHLIB_FORCE_ALL = @MKSHLIB_FORCE_ALL@ -MKSHLIB_UNFORCE_ALL = @MKSHLIB_UNFORCE_ALL@ -DSO_LDOPTS = @DSO_LDOPTS@ -DLL_SUFFIX = @DLL_SUFFIX@ - -NO_LD_ARCHIVE_FLAGS = @NO_LD_ARCHIVE_FLAGS@ - -GTK_CONFIG = @GTK_CONFIG@ -TK_CFLAGS = @TK_CFLAGS@ -TK_LIBS = @TK_LIBS@ - -CAIRO_FT_CFLAGS = @CAIRO_FT_CFLAGS@ - -MOZ_TREE_FREETYPE = @MOZ_TREE_FREETYPE@ -MOZ_ENABLE_CAIRO_FT = @MOZ_ENABLE_CAIRO_FT@ -MOZ_ENABLE_GTK2 = @MOZ_ENABLE_GTK2@ -MOZ_ENABLE_QT = @MOZ_ENABLE_QT@ -MOZ_ENABLE_XREMOTE = @MOZ_ENABLE_XREMOTE@ -MOZ_ENABLE_DWRITE_FONT = @MOZ_ENABLE_DWRITE_FONT@ -MOZ_ENABLE_D2D_SURFACE = @MOZ_ENABLE_D2D_SURFACE@ -MOZ_ENABLE_D3D9_LAYER = @MOZ_ENABLE_D3D9_LAYER@ -MOZ_ENABLE_D3D10_LAYER = @MOZ_ENABLE_D3D10_LAYER@ -MOZ_METRO = @MOZ_METRO@ -MAKEPRI = @MAKEPRI@ -CRTDLLVERSION = @CRTDLLVERSION@ -CRTEXPDLLVERSION = @CRTEXPDLLVERSION@ - -MOZ_GTK2_CFLAGS = @MOZ_GTK2_CFLAGS@ -MOZ_GTK2_LIBS = @MOZ_GTK2_LIBS@ - -MOZ_QT_CFLAGS = @MOZ_QT_CFLAGS@ -MOZ_QT_LIBS = @MOZ_QT_LIBS@ -MOZ_ENABLE_QTNETWORK = @MOZ_ENABLE_QTNETWORK@ -MOZ_ENABLE_QMSYSTEM2 = @MOZ_ENABLE_QMSYSTEM2@ -MOZ_ENABLE_QTMOBILITY = @MOZ_ENABLE_QTMOBILITY@ -MOZ_ENABLE_CONTENTACTION = @MOZ_ENABLE_CONTENTACTION@ -MOZ_ENABLE_MEEGOTOUCHSHARE = @MOZ_ENABLE_MEEGOTOUCHSHARE@ -MOZ_ENABLE_CONTENTMANAGER = @MOZ_ENABLE_CONTENTMANAGER@ - -MOZ_DBUS_CFLAGS = @MOZ_DBUS_CFLAGS@ -MOZ_DBUS_LIBS = @MOZ_DBUS_LIBS@ -MOZ_DBUS_GLIB_CFLAGS = @MOZ_DBUS_GLIB_CFLAGS@ -MOZ_DBUS_GLIB_LIBS = @MOZ_DBUS_GLIB_LIBS@ -MOZ_ENABLE_DBUS = @MOZ_ENABLE_DBUS@ - -MOZ_GTHREAD_CFLAGS = @MOZ_GTHREAD_CFLAGS@ -MOZ_GTHREAD_LIBS = @MOZ_GTHREAD_LIBS@ - -FT2_CFLAGS = @FT2_CFLAGS@ -FT2_LIBS = @FT2_LIBS@ - -MOZ_PANGO_CFLAGS = @MOZ_PANGO_CFLAGS@ -MOZ_PANGO_LIBS = @MOZ_PANGO_LIBS@ - -XT_LIBS = @XT_LIBS@ - -MOZ_LIBPROXY_CFLAGS = @MOZ_LIBPROXY_CFLAGS@ -MOZ_LIBPROXY_LIBS = @MOZ_LIBPROXY_LIBS@ -MOZ_ENABLE_LIBPROXY = @MOZ_ENABLE_LIBPROXY@ - -MOZ_LIBNOTIFY_CFLAGS = @MOZ_LIBNOTIFY_CFLAGS@ -MOZ_LIBNOTIFY_LIBS = @MOZ_LIBNOTIFY_LIBS@ -MOZ_ENABLE_LIBNOTIFY = @MOZ_ENABLE_LIBNOTIFY@ - -MOZ_ALSA_LIBS = @MOZ_ALSA_LIBS@ -MOZ_ALSA_CFLAGS = @MOZ_ALSA_CFLAGS@ - -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_GMODULE_LIBS = @GLIB_GMODULE_LIBS@ - -MOZ_NATIVE_MAKEDEPEND = @MOZ_NATIVE_MAKEDEPEND@ - -CL_INCLUDES_PREFIX = @CL_INCLUDES_PREFIX@ - -MOZ_AUTO_DEPS = @MOZ_AUTO_DEPS@ -COMPILER_DEPEND = @COMPILER_DEPEND@ -MDDEPDIR := @MDDEPDIR@ -CC_WRAPPER = @CC_WRAPPER@ -CXX_WRAPPER = @CXX_WRAPPER@ - -MOZ_DEMANGLE_SYMBOLS = @MOZ_DEMANGLE_SYMBOLS@ - -OS_TARGET=@OS_TARGET@ -OS_ARCH=@OS_ARCH@ -OS_RELEASE=@OS_RELEASE@ -OS_TEST=@OS_TEST@ -CPU_ARCH=@CPU_ARCH@ -INTEL_ARCHITECTURE=@INTEL_ARCHITECTURE@ - -# For Solaris build -SOLARIS_SUNPRO_CC = @SOLARIS_SUNPRO_CC@ -SOLARIS_SUNPRO_CXX = @SOLARIS_SUNPRO_CXX@ - -# For AIX build -AIX_OBJMODEL = @AIX_OBJMODEL@ - -# For OS/2 build -MOZ_OS2_TOOLS = @MOZ_OS2_TOOLS@ -MOZ_OS2_HIGH_MEMORY = @MOZ_OS2_HIGH_MEMORY@ - -MOZ_PSM=@MOZ_PSM@ - -MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@ - -# Win32 options -MOZ_BROWSE_INFO = @MOZ_BROWSE_INFO@ -MOZ_TOOLS_DIR = @MOZ_TOOLS_DIR@ -MSMANIFEST_TOOL = @MSMANIFEST_TOOL@ -WIN32_REDIST_DIR = @WIN32_REDIST_DIR@ -MOZ_GLUE_LDFLAGS = @MOZ_GLUE_LDFLAGS@ -MOZ_GLUE_PROGRAM_LDFLAGS = @MOZ_GLUE_PROGRAM_LDFLAGS@ -WIN32_CRT_LIBS = @WIN32_CRT_LIBS@ - -# This is used to pass jemalloc flags to NSS -DLLFLAGS = @DLLFLAGS@ - -# Codesighs tools option, enables win32 mapfiles. -MOZ_MAPINFO = @MOZ_MAPINFO@ - -MOZ_PHOENIX = @MOZ_PHOENIX@ -MOZ_XULRUNNER = @MOZ_XULRUNNER@ - -MOZ_DISTRIBUTION_ID = @MOZ_DISTRIBUTION_ID@ - -MOZ_PLATFORM_MAEMO = @MOZ_PLATFORM_MAEMO@ -MOZ_PLATFORM_MAEMO_CFLAGS = @MOZ_PLATFORM_MAEMO_CFLAGS@ -MOZ_PLATFORM_MAEMO_LIBS = @MOZ_PLATFORM_MAEMO_LIBS@ -MOZ_MAEMO_LIBLOCATION = @MOZ_MAEMO_LIBLOCATION@ - -MOZ_ENABLE_LIBCONIC = @MOZ_ENABLE_LIBCONIC@ -LIBCONIC_CFLAGS = @LIBCONIC_CFLAGS@ -LIBCONIC_LIBS = @LIBCONIC_LIBS@ - -GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ -GSTREAMER_LIBS = @GSTREAMER_LIBS@ - -MACOS_SDK_DIR = @MACOS_SDK_DIR@ -NEXT_ROOT = @NEXT_ROOT@ -GCC_VERSION = @GCC_VERSION@ -UNIVERSAL_BINARY= @UNIVERSAL_BINARY@ -MOZ_CAN_RUN_PROGRAMS = @MOZ_CAN_RUN_PROGRAMS@ -HAVE_DTRACE= @HAVE_DTRACE@ - -VISIBILITY_FLAGS = @VISIBILITY_FLAGS@ -WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@ - -HAVE_ARM_SIMD = @HAVE_ARM_SIMD@ -HAVE_ARM_NEON = @HAVE_ARM_NEON@ -HAVE_GCC_ALIGN_ARG_POINTER = @HAVE_GCC_ALIGN_ARG_POINTER@ -HAVE_COMPILER_FLAG_MSSSE3 = @HAVE_COMPILER_FLAG_MSSSE3@ - -MOZ_THEME_FASTSTRIPE = @MOZ_THEME_FASTSTRIPE@ - -MOZ_SERVICES_AITC = @MOZ_SERVICES_AITC@ -MOZ_SERVICES_NOTIFICATIONS = @MOZ_SERVICES_NOTIFICATIONS@ -MOZ_SERVICES_SYNC = @MOZ_SERVICES_SYNC@ - -MOZ_WEBAPP_RUNTIME = @MOZ_WEBAPP_RUNTIME@ - -MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BRANDING@ - -HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@ -REALTIME_LIBS = @REALTIME_LIBS@ - -MOZ_APP_COMPONENT_LIBS = @MOZ_APP_COMPONENT_LIBS@ -MOZ_APP_EXTRA_LIBS = @MOZ_APP_EXTRA_LIBS@ - -ANDROID_NDK = @ANDROID_NDK@ -ANDROID_TOOLCHAIN = @ANDROID_TOOLCHAIN@ -ANDROID_PLATFORM = @ANDROID_PLATFORM@ -ANDROID_SDK = @ANDROID_SDK@ -ANDROID_PLATFORM_TOOLS = @ANDROID_PLATFORM_TOOLS@ -ANDROID_VERSION = @ANDROID_VERSION@ -ANDROID_SOURCE = @ANDROID_SOURCE@ -STLPORT_SOURCES = @STLPORT_SOURCES@ - -ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@ - -JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@ - -MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@ - -MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@ - -MOZ_PACKAGE_JSSHELL = @MOZ_PACKAGE_JSSHELL@ - -MOZ_LINKER_EXTRACT = @MOZ_LINKER_EXTRACT@ - -MOZ_PER_WINDOW_PRIVATE_BROWSING = @MOZ_PER_WINDOW_PRIVATE_BROWSING@ - +@ALLSUBSTS@ include $(topsrcdir)/config/baseconfig.mk diff --git a/config/makefiles/autotargets.mk b/config/makefiles/autotargets.mk index 5d6daa5fd943..794d95bcf0a8 100644 --- a/config/makefiles/autotargets.mk +++ b/config/makefiles/autotargets.mk @@ -57,14 +57,17 @@ mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done)) %/.mkdir.done: # mkdir -p -p => mkdir -p $(subst $(space)-p,$(null),$(MKDIR)) -p $(dir $@) - @$(TOUCH) $@ +# Make the timestamp old enough for not being a problem with symbolic links +# targets depending on it. Use Jan 3, 1970 to accomodate any timezone where +# 197001010000 would translate to something older than epoch. + @touch -t 197001030000 $@ # A handful of makefiles are attempting "mkdir dot". Likely not intended # or stale logic so add a stub target to handle the request and warn for now. .mkdir.done: ifndef NOWARN_AUTOTARGETS # { @echo "WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)" - @$(TOUCH) $@ + @touch -t 197001030000 $@ endif #} INCLUDED_AUTOTARGETS_MK = 1 diff --git a/config/rules.mk b/config/rules.mk index 28508b7a43b0..43fc7632ffe9 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -32,7 +32,7 @@ ifdef SDK_HEADERS EXPORTS += $(SDK_HEADERS) endif -REPORT_BUILD = @echo $(notdir $<) +REPORT_BUILD = $(info $(notdir $<)) ifeq ($(OS_ARCH),OS2) EXEC = @@ -45,12 +45,18 @@ ifdef SYSTEM_LIBXUL SKIP_COPY_XULRUNNER=1 endif -# ELOG prints out failed command when building silently (gmake -s). +# ELOG prints out failed command when building silently (gmake -s). Pymake +# prints out failed commands anyway, so ELOG just makes things worse by +# forcing shell invocations. +ifndef .PYMAKE ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS)))) ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh else ELOG := -endif +endif # -s +else + ELOG := +endif # ifndef .PYMAKE _VPATH_SRCS = $(abspath $<) @@ -101,7 +107,7 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) $(if $(JS_SHARED_LIBRARY),,$(MOZ_ZLIB_LIBS)) # ...and run them the usual way check:: @@ -336,8 +342,8 @@ XPIDL_GEN_DIR = _xpidlgen ifdef MOZ_UPDATE_XTERM # Its good not to have a newline at the end of the titlebar string because it # makes the make -s output easier to read. Echo -n does not work on all -# platforms, but we can trick sed into doing it. -UPDATE_TITLE = sed -e "s!Y!$(1) in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2)!" $(MOZILLA_DIR)/config/xterm.str; +# platforms, but we can trick printf into doing it. +UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2) ; endif define SUBMAKE # $(call SUBMAKE,target,directory) @@ -1226,17 +1232,9 @@ PREF_PPFLAGS = --line-endings=crlf endif ifndef NO_DIST_INSTALL -$(FINAL_TARGET)/$(PREF_DIR): - $(NSINSTALL) -D $@ - -libs:: $(FINAL_TARGET)/$(PREF_DIR) -libs:: $(PREF_JS_EXPORTS) - $(EXIT_ON_ERROR) \ - for i in $^; do \ - dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +PREF_JS_EXPORTS_PATH := $(FINAL_TARGET)/$(PREF_DIR) +PREF_JS_EXPORTS_FLAGS := $(PREF_PPFLAGS) +PP_TARGETS += PREF_JS_EXPORTS endif endif @@ -1316,6 +1314,7 @@ libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt ifndef NO_DIST_INSTALL $(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components) ifndef NO_INTERFACES_MANIFEST +libs:: $(call mkdir_deps,$(FINAL_TARGET)/components) @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt" @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest" endif @@ -1366,22 +1365,15 @@ endif endif ifdef EXTRA_PP_COMPONENTS -libs:: $(EXTRA_PP_COMPONENTS) ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/components; \ - for i in $^; do \ - fname=`basename $$i`; \ - dest=$(FINAL_TARGET)/components/$${fname}; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components +PP_TARGETS += EXTRA_PP_COMPONENTS endif endif EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)) ifneq (,$(EXTRA_MANIFESTS)) -libs:: +libs:: $(call mkdir_deps,$(FINAL_TARGET)) $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))) endif @@ -1399,17 +1391,10 @@ endif endif ifdef EXTRA_PP_JS_MODULES -libs:: $(EXTRA_PP_JS_MODULES) ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(JS_MODULES_PATH); \ - for i in $^; do \ - dest=$(JS_MODULES_PATH)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +EXTRA_PP_JS_MODULES_PATH := $(JS_MODULES_PATH) +PP_TARGETS += EXTRA_PP_JS_MODULES endif - endif ################################################################################ @@ -1480,31 +1465,15 @@ endif endif ifneq ($(DIST_FILES),) -$(DIST)/bin: - $(NSINSTALL) -D $@ - -libs:: $(DIST)/bin -libs:: $(DIST_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done +DIST_FILES_PATH := $(FINAL_TARGET) +DIST_FILES_FLAGS := $(XULAPP_DEFINES) +PP_TARGETS += DIST_FILES endif ifneq ($(DIST_CHROME_FILES),) -libs:: $(DIST_CHROME_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/chrome/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done +DIST_CHROME_FILES_PATH := $(FINAL_TARGET)/chrome +DIST_CHROME_FILES_FLAGS := $(XULAPP_DEFINES) +PP_TARGETS += DIST_CHROME_FILES endif ifneq ($(XPI_PKGNAME),) @@ -1662,6 +1631,58 @@ TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS) endif endif +################################################################################ +# Install/copy rules +# +# The INSTALL_TARGETS variable contains a list of all install target +# categories. Each category defines a list of files, an install destination, +# and whether the files are executables or not. +# +# FOO_FILES := foo bar +# FOO_EXECUTABLES := baz +# FOO_DEST := target_path +# INSTALL_TARGETS += FOO +define install_file_template +libs:: $(2)/$(notdir $(1)) +$(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) + $(INSTALL) $(3) $$< $${@D} +endef +$(foreach category,$(INSTALL_TARGETS),\ + $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\ + $(foreach file,$($(category)_FILES),\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS1)))\ + )\ + $(foreach file,$($(category)_EXECUTABLES),\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS2)))\ + )\ +) + +################################################################################ +# Preprocessing rules +# +# The PP_TARGETS variable contains a list of all preprocessing target +# categories. Each category defines a target path, and optional extra flags +# like the following: +# +# FOO_PATH := target_path +# FOO_FLAGS := -Dsome_flag +# PP_TARGETS += FOO + +# preprocess_file_template defines preprocessing rules. +# $(call preprocess_file_template, source_file, target_path, extra_flags) +define preprocess_file_template +$(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) $$(GLOBAL_DEPS) + $$(RM) $$@ + $$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(3) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@ +libs:: $(2)/$(notdir $(1)) +endef + +$(foreach category,$(PP_TARGETS),\ + $(foreach file,$($(category)),\ + $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_FLAGS)))\ + )\ + ) + ################################################################################ # Special gmake rules. ################################################################################ @@ -1761,4 +1782,3 @@ include $(topsrcdir)/config/makefiles/autotargets.mk ifneq ($(NULL),$(AUTO_DEPS)) default all libs tools export:: $(AUTO_DEPS) endif - diff --git a/config/xterm.str b/config/xterm.str deleted file mode 100644 index 07e5905ed7cb..000000000000 --- a/config/xterm.str +++ /dev/null @@ -1 +0,0 @@ -]0;gmake: Y \ No newline at end of file diff --git a/configure.in b/configure.in index 52e5eb84b8e3..3499a0a31294 100644 --- a/configure.in +++ b/configure.in @@ -195,10 +195,10 @@ if test -n "$gonkdir" ; then CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera" CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS" - LIBS="$LIBS $STLPORT_LIBS" - dnl Add -llog by default, since we use it all over the place. - LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ -llog $LDFLAGS" + LIBS="$LIBS -llog $STLPORT_LIBS" + + LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ $LDFLAGS" dnl prevent cross compile section from using these flags as host flags if test -z "$HOST_CPPFLAGS" ; then @@ -1993,16 +1993,6 @@ case "$target" in MOZ_FIX_LINK_PATHS='-Wl,-executable_path,$(LIBXUL_DIST)/bin' ;; -*-freebsd*) - if test `test -x /usr/bin/objformat && /usr/bin/objformat || echo elf` != "elf"; then - DLL_SUFFIX=".so.1.0" - DSO_LDOPTS="-shared" - fi - if test ! "$GNU_CC"; then - DSO_LDOPTS="-Bshareable $DSO_LDOPTS" - fi - ;; - ia64*-hpux*) DLL_SUFFIX=".so" if test ! "$GNU_CC"; then @@ -3194,11 +3184,9 @@ then *-*-freebsd*) AC_DEFINE(_REENTRANT) AC_DEFINE(_THREAD_SAFE) - dnl -pthread links in -lc_r, so don't specify it explicitly. + dnl -pthread links in -lpthread, so don't specify it explicitly. if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" - else - _PTHREAD_LDFLAGS="-lc_r" fi ;; @@ -4800,13 +4788,13 @@ if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT" then AC_SUBST(MOZ_PANGO) - PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION) - - PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION) - AC_SUBST(MOZ_PANGO_CFLAGS) - AC_SUBST(MOZ_PANGO_LIBS) if test "$MOZ_PANGO" then + PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION) + + PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION) + AC_SUBST(MOZ_PANGO_CFLAGS) + AC_SUBST(MOZ_PANGO_LIBS) AC_DEFINE(MOZ_PANGO) else PKG_CHECK_MODULES(FT2, freetype2 > 6.1.0) @@ -6970,7 +6958,11 @@ else *-android*|*-linuxandroid*) AC_DEFINE(MOZ_MEMORY_LINUX) AC_DEFINE(MOZ_MEMORY_ANDROID) - _WRAP_MALLOC=1 + if test -z "$gonkdir"; then + _WRAP_MALLOC=1 + else + AC_DEFINE(MOZ_MEMORY_GONK) + fi MOZ_GLUE_LDFLAGS= ;; *-*linux*) @@ -7788,17 +7780,6 @@ MOZ_ENABLE_SKIA=1, MOZ_ENABLE_SKIA=) if test "$USE_FC_FREETYPE"; then - PKG_CHECK_MODULES(_FONTCONFIG, fontconfig, - [ - if test "$MOZ_PANGO"; then - MOZ_PANGO_CFLAGS="$MOZ_PANGO_CFLAGS $_FONTCONFIG_CFLAGS" - MOZ_PANGO_LIBS="$MOZ_PANGO_LIBS $_FONTCONFIG_LIBS" - else - FT2_CFLAGS="$FT2_CFLAGS $_FONTCONFIG_CFLAGS" - FT2_LIBS="$FT2_LIBS $_FONTCONFIG_LIBS" - fi - ]) - if test "$COMPILE_ENVIRONMENT"; then dnl ======================================================== dnl = Check for freetype2 and its functionality @@ -7843,6 +7824,17 @@ if test "$USE_FC_FREETYPE"; then else AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H) fi + + PKG_CHECK_MODULES(_FONTCONFIG, fontconfig, + [ + if test "$MOZ_PANGO"; then + MOZ_PANGO_CFLAGS="$MOZ_PANGO_CFLAGS $_FONTCONFIG_CFLAGS" + MOZ_PANGO_LIBS="$MOZ_PANGO_LIBS $_FONTCONFIG_LIBS" + else + FT2_CFLAGS="$FT2_CFLAGS $_FONTCONFIG_CFLAGS" + FT2_LIBS="$FT2_LIBS $_FONTCONFIG_LIBS" + fi + ]) fi dnl ======================================================== @@ -8990,7 +8982,6 @@ if test -z "$MOZ_NATIVE_NSPR"; then fi ac_configure_args="$ac_configure_args --with-dist-dir=../../dist" ac_configure_args="$ac_configure_args --prefix=$dist" -ac_configure_args="$ac_configure_args --with-sync-build-files=$_topsrcdir" if test "$MOZ_MEMORY"; then ac_configure_args="$ac_configure_args --enable-jemalloc" fi diff --git a/content/base/crashtests/crashtests.list b/content/base/crashtests/crashtests.list index 226a47514f6a..0b7d1d532260 100644 --- a/content/base/crashtests/crashtests.list +++ b/content/base/crashtests/crashtests.list @@ -110,6 +110,6 @@ load 715056.html load 741163-1.html load 766426.html load 771639.html -asserts(0-1) load 752226-1.html -asserts(0-1) load 752226-2.html +load 752226-1.html +load 752226-2.html HTTP(..) load xhr_abortinprogress.html diff --git a/content/base/public/Element.h b/content/base/public/Element.h index 3fdf81c9bf6a..4d1b51b1acbd 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -7,13 +7,15 @@ #ifndef mozilla_dom_Element_h__ #define mozilla_dom_Element_h__ -#include "mozilla/dom/FragmentOrElement.h" -#include "nsEventStates.h" +#include "mozilla/dom/FragmentOrElement.h" // for base class +#include "nsChangeHint.h" // for enum +#include "nsEventStates.h" // for member class nsEventStateManager; -class nsGlobalWindow; class nsFocusManager; +class nsGlobalWindow; class nsICSSDeclaration; +class nsISMILAttr; // Element-specific flags enum { diff --git a/content/base/public/FragmentOrElement.h b/content/base/public/FragmentOrElement.h index 5133e0a82ff6..07a667911797 100644 --- a/content/base/public/FragmentOrElement.h +++ b/content/base/public/FragmentOrElement.h @@ -12,50 +12,29 @@ #ifndef FragmentOrElement_h___ #define FragmentOrElement_h___ -#include "nsCOMPtr.h" -#include "nsAutoPtr.h" -#include "nsIContent.h" -#include "nsIDOMElement.h" -#include "nsIDOMDocumentFragment.h" -#include "nsILinkHandler.h" -#include "nsNodeUtils.h" -#include "nsAttrAndChildArray.h" -#include "mozFlushType.h" -#include "nsDOMAttributeMap.h" -#include "nsIWeakReference.h" -#include "nsCycleCollectionParticipant.h" -#include "nsIDocument.h" -#include "nsIDOMNodeSelector.h" -#include "nsIDOMXPathNSResolver.h" -#include "nsPresContext.h" -#include "nsIDOMDOMStringMap.h" -#include "nsContentList.h" -#include "nsDOMClassInfoID.h" // DOMCI_DATA -#include "nsIDOMTouchEvent.h" -#include "nsIInlineEventHandlers.h" -#include "mozilla/CORSMode.h" -#include "mozilla/Attributes.h" +#include "nsAttrAndChildArray.h" // member +#include "nsCOMPtr.h" // member +#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_* +#include "nsIContent.h" // base class +#include "nsIDOMNodeSelector.h" // base class +#include "nsIDOMTouchEvent.h" // base class (nsITouchEventReceiver) +#include "nsIDOMXPathNSResolver.h" // base class +#include "nsIInlineEventHandlers.h" // base class +#include "nsINodeList.h" // base class +#include "nsIWeakReference.h" // base class +#include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl -#include "nsISMILAttr.h" - -class nsIDOMAttr; -class nsIDOMEventListener; -class nsIFrame; -class nsIDOMNamedNodeMap; -class nsICSSDeclaration; -class nsIDOMCSSStyleDeclaration; -class nsIURI; -class nsINodeInfo; -class nsIControllers; -class nsEventListenerManager; -class nsIScrollableFrame; -class nsAttrValueOrString; -class nsContentList; -class nsDOMTokenList; class ContentUnbinder; -struct nsRect; - -typedef PRUptrdiff PtrBits; +class nsContentList; +class nsDOMAttributeMap; +class nsDOMTokenList; +class nsIControllers; +class nsICSSDeclaration; +class nsIDocument; +class nsIDOMDOMStringMap; +class nsIDOMNamedNodeMap; +class nsINodeInfo; +class nsIURI; /** * Class that implements the nsIDOMNodeList interface (a list of children of diff --git a/content/base/public/nsIContent.h b/content/base/public/nsIContent.h index 99f0894d5778..367c360e59f2 100644 --- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -5,33 +5,22 @@ #ifndef nsIContent_h___ #define nsIContent_h___ -#include "nsCOMPtr.h" // for already_AddRefed -#include "nsStringGlue.h" -#include "nsCaseTreatment.h" -#include "nsChangeHint.h" -#include "nsINode.h" -#include "nsIDocument.h" // for IsInHTMLDocument -#include "nsCSSProperty.h" +#include "nsCaseTreatment.h" // for enum, cannot be forward-declared +#include "nsCOMPtr.h" // for already_AddRefed in constructor +#include "nsIDocument.h" // for use in inline function (IsInHTMLDocument) +#include "nsINode.h" // for base class // Forward declarations +class nsAString; class nsIAtom; -class nsIDOMEvent; -class nsIContent; -class nsEventListenerManager; class nsIURI; class nsRuleWalker; class nsAttrValue; class nsAttrName; class nsTextFragment; -class nsIDocShell; class nsIFrame; -class nsISMILAttr; -class nsIDOMCSSStyleDeclaration; namespace mozilla { -namespace css { -class StyleRule; -} // namespace css namespace widget { struct IMEState; } // namespace widget diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 094e7f3bd76b..16307c8d5cf1 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -5,80 +5,65 @@ #ifndef nsIDocument_h___ #define nsIDocument_h___ -#include "nsINode.h" -#include "nsStringGlue.h" -#include "nsIDocumentObserver.h" // for nsUpdateType -#include "nsCOMPtr.h" -#include "nsCOMArray.h" -#include "nsIURI.h" -#include "nsILoadGroup.h" -#include "nsCRT.h" -#include "mozFlushType.h" -#include "nsIAtom.h" -#include "nsCompatibility.h" -#include "nsTObserverArray.h" -#include "nsTHashtable.h" -#include "nsHashKeys.h" -#include "nsIVariant.h" -#include "nsIObserver.h" -#include "nsGkAtoms.h" -#include "nsAutoPtr.h" -#include "nsPIDOMWindow.h" -#include "nsSMILAnimationController.h" -#include "nsIScriptGlobalObject.h" -#include "nsIDocumentEncoder.h" -#include "nsIFrameRequestCallback.h" -#include "nsEventStates.h" -#include "nsIStructuredCloneContainer.h" -#include "nsILoadContext.h" +#include "mozFlushType.h" // for enum +#include "nsAutoPtr.h" // for member +#include "nsCOMArray.h" // for member +#include "nsCRT.h" // for NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW +#include "nsCompatibility.h" // for member +#include "nsCOMPtr.h" // for member +#include "nsGkAtoms.h" // for static class members +#include "nsIDocumentEncoder.h" // for member (in nsCOMPtr) +#include "nsIDocumentObserver.h" // for typedef (nsUpdateType) +#include "nsIFrameRequestCallback.h" // for member (in nsCOMPtr) +#include "nsILoadContext.h" // for member (in nsCOMPtr) +#include "nsILoadGroup.h" // for member (in nsCOMPtr) +#include "nsINode.h" // for base class +#include "nsIScriptGlobalObject.h" // for member (in nsCOMPtr) +#include "nsIStructuredCloneContainer.h" // for member (in nsCOMPtr) +#include "nsPIDOMWindow.h" // for use in inline functions +#include "nsPropertyTable.h" // for member +#include "nsTHashtable.h" // for member -class nsIRequest; -class nsPIDOMWindow; -class nsIStreamListener; -class nsIBFCacheEntry; -class nsIContent; -class nsPresContext; -class nsIPresShell; -class nsIDocShell; -class nsStyleSet; -class nsIStyleSheet; -class nsIStyleRule; -class nsCSSStyleSheet; -class nsIViewManager; -class nsIDOMEvent; -class nsIDOMEventTarget; -class nsDeviceContext; -class nsIParser; -class nsIDOMNode; -class nsIDOMElement; -class nsIDOMDocumentFragment; -class nsILineBreaker; -class nsIWordBreaker; -class nsISelection; -class nsIChannel; -class nsIPrincipal; -class nsIDOMDocument; -class nsIDOMDocumentType; -class nsScriptLoader; -class nsIContentSink; -class nsHTMLStyleSheet; -class nsHTMLCSSStyleSheet; -class nsILayoutHistoryState; -class nsIVariant; -class nsIDOMUserDataHandler; -template class nsCOMArray; -class nsIDocumentObserver; -class nsBindingManager; -class nsIDOMNodeList; -class mozAutoSubtreeModified; -struct JSObject; -class nsFrameLoader; -class nsIBoxObject; class imgIRequest; -class nsISHEntry; +class nsAString; +class nsBindingManager; +class nsCSSStyleSheet; class nsDOMNavigationTiming; -class nsWindowSizes; +class nsEventStates; +class nsFrameLoader; +class nsHTMLCSSStyleSheet; +class nsHTMLStyleSheet; +class nsIAtom; +class nsIBFCacheEntry; +class nsIBoxObject; +class nsIChannel; +class nsIContent; +class nsIContentSink; +class nsIDocShell; +class nsIDocumentObserver; +class nsIDOMDocument; +class nsIDOMDocumentFragment; +class nsIDOMDocumentType; +class nsIDOMElement; +class nsIDOMEventTarget; +class nsIDOMNodeList; +class nsILayoutHistoryState; class nsIObjectLoadingContent; +class nsIObserver; +class nsIPresShell; +class nsIPrincipal; +class nsIRequest; +class nsIStreamListener; +class nsIStyleRule; +class nsIStyleSheet; +class nsIURI; +class nsIVariant; +class nsIViewManager; +class nsPresContext; +class nsScriptLoader; +class nsSMILAnimationController; +class nsStyleSet; +class nsWindowSizes; namespace mozilla { namespace css { diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 160cedc1b1f2..0d79acf33736 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -6,20 +6,16 @@ #ifndef nsINode_h___ #define nsINode_h___ -#include "nsIDOMEventTarget.h" -#include "nsEvent.h" -#include "nsPropertyTable.h" -#include "nsTObserverArray.h" -#include "nsINodeInfo.h" -#include "nsCOMPtr.h" -#include "nsWrapperCache.h" -#include "nsIProgrammingLanguage.h" // for ::JAVASCRIPT -#include "nsDOMError.h" -#include "nsDOMString.h" -#include "jspubtd.h" -#include "nsWindowMemoryReporter.h" -#include "nsIVariant.h" -#include "nsGkAtoms.h" +#include "nsCOMPtr.h" // for member, local +#include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty +#include "nsIDOMEventTarget.h" // for base class +#include "nsINodeInfo.h" // member (in nsCOMPtr) +#include "nsIVariant.h" // for use in GetUserData() +#include "nsNodeInfoManager.h" // for use in NodePrincipal() +#include "nsPropertyTable.h" // for typedefs +#include "nsTObserverArray.h" // for member +#include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS +#include "nsWrapperCache.h" // for base class // Including 'windows.h' will #define GetClassInfo to something else. #ifdef XP_WIN @@ -28,26 +24,23 @@ #endif #endif +class nsAttrAndChildArray; +class nsChildContentList; class nsIContent; class nsIDocument; -class nsIDOMEvent; -class nsIDOMNode; class nsIDOMElement; +class nsIDOMNode; class nsIDOMNodeList; +class nsIDOMUserDataHandler; +class nsIEditor; +class nsIFrame; +class nsIMutationObserver; class nsINodeList; class nsIPresShell; -class nsEventChainVisitor; -class nsEventChainPreVisitor; -class nsEventChainPostVisitor; -class nsEventListenerManager; class nsIPrincipal; -class nsIMutationObserver; -class nsChildContentList; -class nsNodeWeakReference; +class nsIURI; class nsNodeSupportsWeakRefTearoff; -class nsIEditor; -class nsIDOMUserDataHandler; -class nsAttrAndChildArray; +class nsNodeWeakReference; class nsXPCClassInfo; namespace mozilla { @@ -56,6 +49,12 @@ class Element; } // namespace dom } // namespace mozilla +namespace JS { +class Value; +} + +inline void SetDOMStringToNull(nsAString& aString); + enum { // This bit will be set if the node has a listener manager. NODE_HAS_LISTENERMANAGER = 0x00000001U, @@ -150,19 +149,6 @@ enum { NODE_TYPE_SPECIFIC_BITS_OFFSET = 20 }; -// Useful inline function for getting a node given an nsIContent and an -// nsIDocument. Returns the first argument cast to nsINode if it is non-null, -// otherwise returns the second (which may be null). We use type variables -// instead of nsIContent* and nsIDocument* because the actual types must be -// known for the cast to work. -template -inline nsINode* NODE_FROM(C& aContent, D& aDocument) -{ - if (aContent) - return static_cast(aContent); - return static_cast(aDocument); -} - /** * Class used to detect unexpected mutations. To use the class create an * nsMutationGuard on the stack before unexpected mutations could occur. @@ -1559,6 +1545,19 @@ protected: nsSlots* mSlots; }; +// Useful inline function for getting a node given an nsIContent and an +// nsIDocument. Returns the first argument cast to nsINode if it is non-null, +// otherwise returns the second (which may be null). We use type variables +// instead of nsIContent* and nsIDocument* because the actual types must be +// known for the cast to work. +template +inline nsINode* NODE_FROM(C& aContent, D& aDocument) +{ + if (aContent) + return static_cast(aContent); + return static_cast(aDocument); +} + extern const nsIID kThisPtrOffsetsSID; diff --git a/content/base/public/nsINodeInfo.h b/content/base/public/nsINodeInfo.h index 0e9ad597cb22..b8d14adf37af 100644 --- a/content/base/public/nsINodeInfo.h +++ b/content/base/public/nsINodeInfo.h @@ -23,20 +23,19 @@ #ifndef nsINodeInfo_h___ #define nsINodeInfo_h___ -#include "nsISupports.h" -#include "nsIAtom.h" -#include "nsINameSpaceManager.h" -#include "nsNodeInfoManager.h" -#include "nsCOMPtr.h" +#include "nsCOMPtr.h" // for member +#include "nsIAtom.h" // for member (in nsCOMPtr) +#include "nsINameSpaceManager.h" // for kNameSpaceID_* +#include "nsISupports.h" // for base class #ifdef MOZILLA_INTERNAL_API #include "nsDOMString.h" #endif -// Forward declarations class nsIDocument; class nsIURI; class nsIPrincipal; +class nsNodeInfoManager; // IID for the nsINodeInfo interface #define NS_INODEINFO_IID \ diff --git a/content/base/public/nsIObjectLoadingContent.idl b/content/base/public/nsIObjectLoadingContent.idl index 2e1f346a3132..02df0defdc71 100644 --- a/content/base/public/nsIObjectLoadingContent.idl +++ b/content/base/public/nsIObjectLoadingContent.idl @@ -24,6 +24,9 @@ interface nsIURI; [scriptable, uuid(e3e284a3-b4a8-49ef-af6b-c8c4a158db86)] interface nsIObjectLoadingContent : nsISupports { + /** + * See notes in nsObjectLoadingContent.h + */ const unsigned long TYPE_LOADING = 0; const unsigned long TYPE_IMAGE = 1; const unsigned long TYPE_PLUGIN = 2; diff --git a/content/base/public/nsIXMLHttpRequest.idl b/content/base/public/nsIXMLHttpRequest.idl index c931180b9d8a..6a281f313876 100644 --- a/content/base/public/nsIXMLHttpRequest.idl +++ b/content/base/public/nsIXMLHttpRequest.idl @@ -395,7 +395,7 @@ interface nsIXHRSendable : nsISupports { /** * @deprecated */ -[deprecated, scriptable, uuid(8ae70a39-edf1-40b4-a992-472d23421c25)] +[scriptable, uuid(8ae70a39-edf1-40b4-a992-472d23421c25)] interface nsIJSXMLHttpRequest : nsISupports { }; diff --git a/content/base/src/nsDOMMutationObserver.cpp b/content/base/src/nsDOMMutationObserver.cpp index 5993417d6d49..aa504a1a16fb 100644 --- a/content/base/src/nsDOMMutationObserver.cpp +++ b/content/base/src/nsDOMMutationObserver.cpp @@ -6,6 +6,7 @@ #include "nsDOMMutationObserver.h" #include "nsDOMClassInfoID.h" +#include "nsDOMError.h" #include "nsIClassInfo.h" #include "nsIXPCScriptable.h" #include "nsIScriptGlobalObject.h" diff --git a/content/base/src/nsEventSource.cpp b/content/base/src/nsEventSource.cpp index b6141cfd45d5..fa9433d9d398 100644 --- a/content/base/src/nsEventSource.cpp +++ b/content/base/src/nsEventSource.cpp @@ -33,6 +33,7 @@ #include "nsDOMEventTargetHelper.h" #include "mozilla/Attributes.h" #include "nsDOMClassInfoID.h" +#include "nsDOMError.h" using namespace mozilla; diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index c81a5d3f53c7..4d4891577c00 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -10,6 +10,7 @@ #include "ContentChild.h" #include "ContentParent.h" #include "nsContentUtils.h" +#include "nsDOMError.h" #include "nsIXPConnect.h" #include "jsapi.h" #include "nsJSUtils.h" @@ -31,6 +32,9 @@ #ifdef ANDROID #include #endif +#ifdef XP_WIN +#include +#endif using namespace mozilla; using namespace mozilla::dom; @@ -293,6 +297,11 @@ nsFrameMessageManager::Dump(const nsAString& aStr) { #ifdef ANDROID __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get()); +#endif +#ifdef XP_WIN + if (IsDebuggerPresent()) { + OutputDebugStringW(PromiseFlatString(aStr).get()); + } #endif fputs(NS_ConvertUTF16toUTF8(aStr).get(), stdout); fflush(stdout); diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 23cc510d18b9..d5c97e6cfa40 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -48,6 +48,7 @@ class nsIDOMCSSStyleDeclaration; class nsIURI; class nsINodeInfo; class nsIControllers; +class nsEventChainVisitor; class nsEventListenerManager; class nsIScrollableFrame; class nsAttrValueOrString; diff --git a/content/base/src/nsGkAtoms.h b/content/base/src/nsGkAtoms.h index bc34caeed842..d8204fdd2234 100644 --- a/content/base/src/nsGkAtoms.h +++ b/content/base/src/nsGkAtoms.h @@ -12,7 +12,7 @@ #ifndef nsGkAtoms_h___ #define nsGkAtoms_h___ -#include "nsIAtom.h" +class nsIAtom; class nsGkAtoms { public: diff --git a/content/base/src/nsNodeInfoManager.h b/content/base/src/nsNodeInfoManager.h index a57c99c52f83..30e57359618b 100644 --- a/content/base/src/nsNodeInfoManager.h +++ b/content/base/src/nsNodeInfoManager.h @@ -10,24 +10,22 @@ #ifndef nsNodeInfoManager_h___ #define nsNodeInfoManager_h___ -#include "nsCOMPtr.h" // for already_AddRefed -#include "plhash.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/Attributes.h" +#include "mozilla/Attributes.h" // for MOZ_FINAL +#include "nsCOMPtr.h" // for member +#include "nsCycleCollectionParticipant.h" // for NS_DECL_CYCLE_* +#include "plhash.h" // for typedef PLHashNumber +class nsAString; +class nsBindingManager; class nsIAtom; class nsIDocument; -class nsINodeInfo; -class nsNodeInfo; -class nsIPrincipal; -class nsIURI; -class nsDocument; class nsIDOMDocumentType; -class nsIDOMDocument; -class nsAString; -class nsIDOMNamedNodeMap; -class nsXULPrototypeDocument; -class nsBindingManager; +class nsINodeInfo; +class nsIPrincipal; +class nsNodeInfo; +struct PLHashEntry; +struct PLHashTable; +template struct already_AddRefed; class nsNodeInfoManager MOZ_FINAL : public nsISupports { diff --git a/content/base/src/nsNodeUtils.h b/content/base/src/nsNodeUtils.h index 03219c3e9b89..f3ea1ca39919 100644 --- a/content/base/src/nsNodeUtils.h +++ b/content/base/src/nsNodeUtils.h @@ -6,8 +6,8 @@ #ifndef nsNodeUtils_h___ #define nsNodeUtils_h___ -#include "nsINode.h" -#include "nsIContent.h" +#include "nsIContent.h" // for use in inline function (ParentChainChanged) +#include "nsIMutationObserver.h" // for use in inline function (ParentChainChanged) struct CharacterDataChangeInfo; struct JSContext; diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index 9a7635f834ee..dda2fd4d2489 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -81,61 +81,66 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc"); #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG) +/// +/// Runnables and helper classes +/// + class nsAsyncInstantiateEvent : public nsRunnable { public: - nsObjectLoadingContent *mContent; - nsAsyncInstantiateEvent(nsObjectLoadingContent* aContent) - : mContent(aContent) - { - static_cast(mContent)->AddRef(); - } + nsAsyncInstantiateEvent(nsObjectLoadingContent *aContent) + : mContent(aContent) {} - ~nsAsyncInstantiateEvent() - { - static_cast(mContent)->Release(); - } + ~nsAsyncInstantiateEvent() {} NS_IMETHOD Run(); + +private: + nsCOMPtr mContent; }; NS_IMETHODIMP nsAsyncInstantiateEvent::Run() { + nsObjectLoadingContent *objLC = + static_cast(mContent.get()); + // do nothing if we've been revoked - if (mContent->mPendingInstantiateEvent != this) { + if (objLC->mPendingInstantiateEvent != this) { return NS_OK; } - mContent->mPendingInstantiateEvent = nullptr; + objLC->mPendingInstantiateEvent = nullptr; - return mContent->SyncStartPluginInstance(); + return objLC->SyncStartPluginInstance(); } // Checks to see if the content for a plugin instance has a parent. // The plugin instance is stopped if there is no parent. class InDocCheckEvent : public nsRunnable { public: - nsCOMPtr mContent; + InDocCheckEvent(nsObjectLoadingContent *aContent) + : mContent(aContent) {} - InDocCheckEvent(nsIContent* aContent) - : mContent(aContent) - { - } - - ~InDocCheckEvent() - { - } + ~InDocCheckEvent() {} NS_IMETHOD Run(); + +private: + nsCOMPtr mContent; }; NS_IMETHODIMP InDocCheckEvent::Run() { - if (!mContent->IsInDoc()) { - nsCOMPtr olc = do_QueryInterface(mContent); - if (olc) { - olc->StopPluginInstance(); - } + nsObjectLoadingContent *objLC = + static_cast(mContent.get()); + + nsCOMPtr content = + do_QueryInterface(static_cast(objLC)); + + if (!content->IsInDoc()) { + nsObjectLoadingContent *objLC = + static_cast(mContent.get()); + objLC->UnloadObject(); } return NS_OK; } @@ -145,50 +150,51 @@ InDocCheckEvent::Run() */ class nsPluginErrorEvent : public nsRunnable { public: - nsCOMPtr mContent; - PluginSupportState mState; - - nsPluginErrorEvent(nsIContent* aContent, PluginSupportState aState) + nsPluginErrorEvent(nsIContent* aContent, + nsObjectLoadingContent::FallbackType aFallbackType) : mContent(aContent), - mState(aState) - {} + mFallbackType(aFallbackType) {} ~nsPluginErrorEvent() {} NS_IMETHOD Run(); + +private: + nsCOMPtr mContent; + nsObjectLoadingContent::FallbackType mFallbackType; }; NS_IMETHODIMP nsPluginErrorEvent::Run() { - LOG(("OBJLC []: Firing plugin not found event for content %p\n", - mContent.get())); nsString type; - switch (mState) { - case ePluginClickToPlay: - type = NS_LITERAL_STRING("PluginClickToPlay"); - break; - case ePluginVulnerableUpdatable: + switch (mFallbackType) { + case nsObjectLoadingContent::eFallbackVulnerableUpdatable: type = NS_LITERAL_STRING("PluginVulnerableUpdatable"); break; - case ePluginVulnerableNoUpdate: + case nsObjectLoadingContent::eFallbackVulnerableNoUpdate: type = NS_LITERAL_STRING("PluginVulnerableNoUpdate"); break; - case ePluginUnsupported: + case nsObjectLoadingContent::eFallbackClickToPlay: + type = NS_LITERAL_STRING("PluginClickToPlay"); + break; + case nsObjectLoadingContent::eFallbackUnsupported: type = NS_LITERAL_STRING("PluginNotFound"); break; - case ePluginDisabled: + case nsObjectLoadingContent::eFallbackDisabled: type = NS_LITERAL_STRING("PluginDisabled"); break; - case ePluginBlocklisted: + case nsObjectLoadingContent::eFallbackBlocklisted: type = NS_LITERAL_STRING("PluginBlocklisted"); break; - case ePluginOutdated: + case nsObjectLoadingContent::eFallbackOutdated: type = NS_LITERAL_STRING("PluginOutdated"); break; default: return NS_OK; } + LOG(("OBJLC [%p]: nsPluginErrorEvent firing '%s'", + mContent.get(), NS_ConvertUTF16toUTF8(type).get())); nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent, type, true, true); @@ -229,7 +235,7 @@ public: NS_IMETHODIMP nsPluginCrashedEvent::Run() { - LOG(("OBJLC []: Firing plugin crashed event for content %p\n", + LOG(("OBJLC [%p]: Firing plugin crashed event\n", mContent.get())); nsCOMPtr domDoc = @@ -251,7 +257,7 @@ nsPluginCrashedEvent::Run() event->InitEvent(NS_LITERAL_STRING("PluginCrashed"), true, true); event->SetTrusted(true); event->GetInternalNSEvent()->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH; - + nsCOMPtr variant; // add a "pluginDumpID" property to this event @@ -353,7 +359,8 @@ nsStopPluginRunnable::Run() if (mTimer) { // Fire 100ms timer to try to tear down this plugin as quickly as // possible once the nesting level comes back down. - nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT); + nsresult rv = mTimer->InitWithCallback(this, 100, + nsITimer::TYPE_ONE_SHOT); if (NS_SUCCEEDED(rv)) { return rv; } @@ -371,82 +378,89 @@ nsStopPluginRunnable::Run() return NS_OK; } -class AutoNotifier { - public: - AutoNotifier(nsObjectLoadingContent* aContent, bool aNotify) : - mContent(aContent), mNotify(aNotify) { - mOldType = aContent->Type(); - mOldState = aContent->ObjectState(); - } - ~AutoNotifier() { - mContent->NotifyStateChanged(mOldType, mOldState, false, mNotify); - } +// You can't take the address of bitfield members, so we have two separate +// classes for these :-/ - /** - * Send notifications now, ignoring the value of mNotify. The new type and - * state is saved, and the destructor will notify again if mNotify is true - * and the values changed. - */ - void Notify() { - NS_ASSERTION(mNotify, "Should not notify when notify=false"); - - mContent->NotifyStateChanged(mOldType, mOldState, true, true); - mOldType = mContent->Type(); - mOldState = mContent->ObjectState(); - } - - private: - nsObjectLoadingContent* mContent; - bool mNotify; - nsObjectLoadingContent::ObjectType mOldType; - nsEventStates mOldState; -}; - -/** - * A class that will automatically fall back if a |rv| variable has a failure - * code when this class is destroyed. It does not notify. - */ -class AutoFallback { - public: - AutoFallback(nsObjectLoadingContent* aContent, const nsresult* rv) - : mContent(aContent), mResult(rv), mPluginState(ePluginOtherState) {} - ~AutoFallback() { - if (NS_FAILED(*mResult)) { - LOG(("OBJLC [%p]: rv=%08x, falling back\n", mContent, *mResult)); - mContent->Fallback(false); - if (mPluginState != ePluginOtherState) { - mContent->mFallbackReason = mPluginState; - } - } - } - - /** - * This should be set to something other than ePluginOtherState to indicate - * a specific failure that should be passed on. - */ - void SetPluginState(PluginSupportState aState) { - NS_ASSERTION(aState != ePluginOtherState, "Should not be setting ePluginOtherState"); - mPluginState = aState; - } - private: - nsObjectLoadingContent* mContent; - const nsresult* mResult; - PluginSupportState mPluginState; -}; - -/** - * A class that automatically sets mInstantiating to false when it goes - * out of scope. - */ +// Sets a object's mInstantiating bit to false when destroyed class AutoSetInstantiatingToFalse { - public: - AutoSetInstantiatingToFalse(nsObjectLoadingContent* objlc) : mContent(objlc) {} - ~AutoSetInstantiatingToFalse() { mContent->mInstantiating = false; } - private: - nsObjectLoadingContent* mContent; +public: + AutoSetInstantiatingToFalse(nsObjectLoadingContent *aContent) + : mContent(aContent) {} + ~AutoSetInstantiatingToFalse() { mContent->mInstantiating = false; } +private: + nsObjectLoadingContent* mContent; }; -// helper functions +// Sets a object's mInstantiating bit to false when destroyed +class AutoSetLoadingToFalse { +public: + AutoSetLoadingToFalse(nsObjectLoadingContent *aContent) + : mContent(aContent) {} + ~AutoSetLoadingToFalse() { mContent->mIsLoading = false; } +private: + nsObjectLoadingContent* mContent; +}; + +/// +/// Helper functions +/// + +static bool +IsSuccessfulRequest(nsIRequest* aRequest) +{ + nsresult status; + nsresult rv = aRequest->GetStatus(&status); + if (NS_FAILED(rv) || NS_FAILED(status)) { + return false; + } + + // This may still be an error page or somesuch + nsCOMPtr httpChan(do_QueryInterface(aRequest)); + if (httpChan) { + bool success; + rv = httpChan->GetRequestSucceeded(&success); + if (NS_FAILED(rv) || !success) { + return false; + } + } + + // Otherwise, the request is successful + return true; +} + +static bool +CanHandleURI(nsIURI* aURI) +{ + nsCAutoString scheme; + if (NS_FAILED(aURI->GetScheme(scheme))) { + return false; + } + + nsIIOService* ios = nsContentUtils::GetIOService(); + if (!ios) + return false; + + nsCOMPtr handler; + ios->GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); + if (!handler) { + return false; + } + + nsCOMPtr extHandler = + do_QueryInterface(handler); + // We can handle this URI if its protocol handler is not the external one + return extHandler == nullptr; +} + +// Helper for tedious URI equality syntax when one or both arguments may be +// null and URIEquals(null, null) should be true +static bool inline +URIEquals(nsIURI *a, nsIURI *b) +{ + bool equal; + return (!a && !b) || (a && b && NS_SUCCEEDED(a->Equals(b, &equal)) && equal); +} + static bool IsSupportedImage(const nsCString& aMimeType) { @@ -460,77 +474,6 @@ IsSupportedImage(const nsCString& aMimeType) return NS_SUCCEEDED(rv) && supported; } -nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMEType) -{ - nsCOMPtr pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); - nsPluginHost *pluginHost = static_cast(pluginHostCOM.get()); - if (!pluginHost) { - return NS_ERROR_FAILURE; - } - - nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get()); - - // Check to see if the plugin is disabled before deciding if it - // should be in the "click to play" state, since we only want to - // display "click to play" UI for enabled plugins. - if (NS_FAILED(rv)) { - return rv; - } - - if (!pluginHost->IsPluginClickToPlayForType(aMIMEType.get())) { - mCTPPlayable = true; - } - - if (!mCTPPlayable) { - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - MOZ_ASSERT(thisContent); - nsIDocument* ownerDoc = thisContent->OwnerDoc(); - - nsCOMPtr window = ownerDoc->GetWindow(); - if (!window) { - return NS_ERROR_FAILURE; - } - nsCOMPtr topWindow; - rv = window->GetTop(getter_AddRefs(topWindow)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr topDocument; - rv = topWindow->GetDocument(getter_AddRefs(topDocument)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr topDoc = do_QueryInterface(topDocument); - - nsCOMPtr permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - bool allowPerm = false; - // For now we always say that the system principal uses click-to-play since - // that maintains current behavior and we have tests that expect this. - // What we really should do is disable plugins entirely in pages that use - // the system principal, i.e. in chrome pages. That way the click-to-play - // code here wouldn't matter at all. Bug 775301 is tracking this. - if (!nsContentUtils::IsSystemPrincipal(topDoc->NodePrincipal())) { - PRUint32 permission; - rv = permissionManager->TestPermissionFromPrincipal(topDoc->NodePrincipal(), - "plugins", - &permission); - NS_ENSURE_SUCCESS(rv, rv); - allowPerm = permission == nsIPermissionManager::ALLOW_ACTION; - } - - PRUint32 state; - rv = pluginHost->GetBlocklistStateForType(aMIMEType.get(), &state); - NS_ENSURE_SUCCESS(rv, rv); - - if (allowPerm && - state != nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE && - state != nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) { - mCTPPlayable = true; - } else { - return NS_ERROR_PLUGIN_CLICKTOPLAY; - } - } - - return NS_OK; -} - static void GetExtensionFromURI(nsIURI* uri, nsCString& ext) { @@ -552,41 +495,105 @@ GetExtensionFromURI(nsIURI* uri, nsCString& ext) * Checks whether a plugin exists and is enabled for the extension * in the given URI. The MIME type is returned in the mimeType out parameter. */ -bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType) +bool +IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType) { nsCAutoString ext; GetExtensionFromURI(uri, ext); - bool enabled = false; if (ext.IsEmpty()) { return false; } - nsCOMPtr pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); - nsPluginHost *pluginHost = static_cast(pluginHostCOM.get()); + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); + if (!pluginHost) { + NS_NOTREACHED("No pluginhost"); return false; } const char* typeFromExt; - if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) { + nsresult rv = pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt); + if (NS_SUCCEEDED(rv)) { mimeType = typeFromExt; - enabled = true; - - if (!pluginHost->IsPluginClickToPlayForType(mimeType.get())) { - mCTPPlayable = true; - } - } - - if (!mCTPPlayable) { - return false; - } else { - return enabled; + return true; } + return false; } nsresult -nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* /*aParent*/, +IsPluginEnabledForType(const nsCString& aMIMEType) +{ + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); + + if (!pluginHost) { + NS_NOTREACHED("No pluginhost"); + return false; + } + + nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get()); + + // Check to see if the plugin is disabled before deciding if it + // should be in the "click to play" state, since we only want to + // display "click to play" UI for enabled plugins. + if (NS_FAILED(rv)) { + return rv; + } + + return NS_OK; +} + +/// +/// Member Functions +/// + +bool +nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType) +{ + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); + + nsresult rv; + nsCOMPtr info( + do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv)); + PRUint32 supported; + if (info) { + nsCOMPtr webNav; + nsIDocument* currentDoc = thisContent->GetCurrentDoc(); + if (currentDoc) { + webNav = do_GetInterface(currentDoc->GetScriptGlobalObject()); + } + rv = info->IsTypeSupported(aMimeType, webNav, &supported); + } + + if (NS_SUCCEEDED(rv)) { + if (supported == nsIWebNavigationInfo::UNSUPPORTED) { + // Try a stream converter + // NOTE: We treat any type we can convert from as a supported type. If a + // type is not actually supported, the URI loader will detect that and + // return an error, and we'll fallback. + nsCOMPtr convServ = + do_GetService("@mozilla.org/streamConverters;1"); + bool canConvert = false; + if (convServ) { + rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert); + } + return NS_SUCCEEDED(rv) && canConvert; + } + + // Don't want to support plugins as documents + return supported != nsIWebNavigationInfo::PLUGIN; + } + + return false; +} + +nsresult +nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, + nsIContent* /*aParent*/, nsIContent* /*aBindingParent*/, bool /*aCompileEventHandlers*/) { @@ -599,37 +606,70 @@ nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* /*aParent void nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/) { - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); MOZ_ASSERT(thisContent); nsIDocument* ownerDoc = thisContent->OwnerDoc(); ownerDoc->RemovePlugin(this); + + if (mType == eType_Plugin) { + // we'll let the plugin continue to run at least until we get back to + // the event loop. If we get back to the event loop and the node + // has still not been added back to the document then we tear down the + // plugin + nsCOMPtr event = new InDocCheckEvent(this); + + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) { + appShell->RunInStableState(event); + } + } else { + /// XXX(johns): The implementation for GenericFrame notes that ideally we + /// would keep the docshell around, but trash the frameloader + UnloadObject(); + } + } nsObjectLoadingContent::nsObjectLoadingContent() : mPendingInstantiateEvent(nullptr) , mChannel(nullptr) , mType(eType_Loading) + , mFallbackType(eFallbackAlternate) + , mChannelLoaded(false) , mInstantiating(false) - , mUserDisabled(false) - , mSuppressed(false) , mNetworkCreated(true) + , mActivated(false) , mIsStopping(false) - , mSrcStreamLoading(false) - , mFallbackReason(ePluginOtherState) - , mCTPPlayable(false) - , mActivated(false) {} + , mIsLoading(false) + , mSrcStreamLoading(false) {} nsObjectLoadingContent::~nsObjectLoadingContent() { - DestroyImageLoadingContent(); + // Should have been unbound from the tree at this point, and InDocCheckEvent + // keeps us alive if (mFrameLoader) { + NS_NOTREACHED("Should not be tearing down frame loaders at this point"); mFrameLoader->Destroy(); } + if (mInstanceOwner) { + // This is especially bad as delayed stop will try to hold on to this + // object... + NS_NOTREACHED("Should not be tearing down a plugin at this point!"); + StopPluginInstance(); + } + DestroyImageLoadingContent(); } nsresult -nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI) +nsObjectLoadingContent::InstantiatePluginInstance() { + if (mType != eType_Plugin) { + LOG(("OBJLC [%p]: Refusing to instantiate non-plugin, " + "type %u", this, mType)); + return NS_OK; + } + // Don't do anything if we already have an active instance. if (mInstanceOwner) { return NS_OK; @@ -646,40 +686,28 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* // can destroy this DOM object. Don't allow that for the scope // of this method. nsCOMPtr kungFuDeathGrip = this; - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - - nsCOMPtr baseURI; - if (!aURI) { - // We need some URI. If we have nothing else, use the base URI. - // XXX(biesi): The code used to do this. Not sure why this is correct... - GetObjectBaseURI(thisContent, getter_AddRefs(baseURI)); - aURI = baseURI; - } + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); // Flush layout so that the plugin is initialized with the latest information. nsIDocument* doc = thisContent->GetCurrentDoc(); if (!doc) { return NS_ERROR_FAILURE; } if (!doc->IsActive()) { - NS_ERROR("Shouldn't be calling InstantiatePluginInstance in an inactive document"); + NS_ERROR("Shouldn't be calling " + "InstantiatePluginInstance in an inactive document"); return NS_ERROR_FAILURE; } doc->FlushPendingNotifications(Flush_Layout); nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv)); - nsPluginHost* pluginHost = static_cast(pluginHostCOM.get()); - if (NS_FAILED(rv)) { - return rv; - } + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); - if (!pluginHost->IsPluginClickToPlayForType(aMimeType)) { - mCTPPlayable = true; - } - - if (!mCTPPlayable) { - return NS_ERROR_PLUGIN_CLICKTOPLAY; + if (!pluginHost) { + NS_NOTREACHED("No pluginhost"); + return false; } // If you add early return(s), be sure to balance this call to @@ -698,13 +726,16 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* if (fullPageMode) { nsCOMPtr stream; - rv = pluginHost->InstantiateFullPagePluginInstance(aMimeType, aURI, this, - getter_AddRefs(mInstanceOwner), getter_AddRefs(stream)); + rv = pluginHost->InstantiateFullPagePluginInstance(mContentType.get(), + mURI.get(), this, + getter_AddRefs(mInstanceOwner), + getter_AddRefs(stream)); if (NS_SUCCEEDED(rv)) { pDoc->SetStreamListener(stream); } } else { - rv = pluginHost->InstantiateEmbeddedPluginInstance(aMimeType, aURI, this, + rv = pluginHost->InstantiateEmbeddedPluginInstance(mContentType.get(), + mURI.get(), this, getter_AddRefs(mInstanceOwner)); } @@ -723,20 +754,20 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* GetPluginInstance(getter_AddRefs(pluginInstance)); if (pluginInstance) { nsCOMPtr pluginTag; - pluginHost->GetPluginTagForInstance(pluginInstance, getter_AddRefs(pluginTag)); - + pluginHost->GetPluginTagForInstance(pluginInstance, + getter_AddRefs(pluginTag)); + nsCOMPtr blocklist = - do_GetService("@mozilla.org/extensions/blocklist;1"); + do_GetService("@mozilla.org/extensions/blocklist;1"); if (blocklist) { PRUint32 blockState = nsIBlocklistService::STATE_NOT_BLOCKED; blocklist->GetPluginBlocklistState(pluginTag, EmptyString(), EmptyString(), &blockState); if (blockState == nsIBlocklistService::STATE_OUTDATED) - FirePluginError(thisContent, ePluginOutdated); + FirePluginError(eFallbackOutdated); } } - mActivated = true; return NS_OK; } @@ -747,7 +778,8 @@ nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged() return; } - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); nsIDocument* ownerDoc = thisContent->OwnerDoc(); if (!ownerDoc->IsActive()) { StopPluginInstance(); @@ -759,261 +791,43 @@ NS_IMETHODIMP nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) { + /// This must call LoadObject, even upon failure, to allow it to either + /// proceed with the load, or trigger fallback content. + SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest"); + LOG(("OBJLC [%p]: Channel OnStartRequest", this)); + if (aRequest != mChannel || !aRequest) { - // This is a bit of an edge case - happens when a new load starts before the - // previous one got here + // happens when a new load starts before the previous one got here return NS_BINDING_ABORTED; } - AutoNotifier notifier(this, true); + NS_ASSERTION(!mChannelLoaded, "mChannelLoaded set already?"); + NS_ASSERTION(!mFinalListener, "mFinalListener exists already?"); - if (!IsSuccessfulRequest(aRequest)) { - LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this)); - Fallback(false); - return NS_BINDING_ABORTED; - } + mChannelLoaded = true; nsCOMPtr chan(do_QueryInterface(aRequest)); NS_ASSERTION(chan, "Why is our request not a channel?"); - nsresult rv = NS_ERROR_UNEXPECTED; - // This fallback variable MUST be declared after the notifier variable. Do NOT - // change the order of the declarations! - AutoFallback fallback(this, &rv); - - nsCString channelType; - rv = chan->GetContentType(channelType); - NS_ENSURE_SUCCESS(rv, rv); - - if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) { - channelType = APPLICATION_OCTET_STREAM; - chan->SetContentType(channelType); - } - - // We want to ignore the channel type if one of the following is true: - // - // 1) The channel type is application/octet-stream or binary/octet-stream - // and we have a type hint (in mContentType) and the type hint is not a - // document type. - // 2) Our type hint is a type that we support with a plugin - // (where "support" means it is enabled or it is click-to-play) - // and this object loading content has the capability to load a plugin. - // We have to be careful here - there might be a plugin that supports - // image types, so make sure the type of the content is not an image. - bool isOctetStream = (channelType.EqualsASCII(APPLICATION_OCTET_STREAM) || - channelType.EqualsASCII(BINARY_OCTET_STREAM)); - ObjectType typeOfContent = GetTypeOfContent(mContentType); - bool caseOne = (isOctetStream && - !mContentType.IsEmpty() && - typeOfContent != eType_Document); - nsresult pluginState = IsPluginEnabledForType(mContentType); - bool pluginSupported = (NS_SUCCEEDED(pluginState) || - pluginState == NS_ERROR_PLUGIN_CLICKTOPLAY); - PRUint32 caps = GetCapabilities(); - bool caseTwo = (pluginSupported && - (caps & eSupportPlugins) && - typeOfContent != eType_Image && - typeOfContent != eType_Document); - if (caseOne || caseTwo) { - // Set the type we'll use for dispatch on the channel. Otherwise we could - // end up trying to dispatch to a nsFrameLoader, which will complain that - // it couldn't find a way to handle application/octet-stream - nsCAutoString typeHint, dummy; - NS_ParseContentType(mContentType, typeHint, dummy); - if (!typeHint.IsEmpty()) { - chan->SetContentType(typeHint); - } - } else { - mContentType = channelType; - } - nsCOMPtr uri; - chan->GetURI(getter_AddRefs(uri)); + + if (IsSuccessfulRequest(aRequest)) { + chan->GetURI(getter_AddRefs(uri)); + } + if (!uri) { + LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this)); + // If the request fails, we still call LoadObject() to handle fallback + // content and notifying of failure. (mChannelLoaded && !mChannel) indicates + // the bad state. + mChannel = nullptr; + LoadObject(true, false); return NS_ERROR_FAILURE; } - if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM) || - mContentType.EqualsASCII(BINARY_OCTET_STREAM)) { - nsCAutoString extType; - if (IsPluginEnabledByExtension(uri, extType)) { - mContentType = extType; - chan->SetContentType(extType); - } - } - - // Now find out what type the content is - // UnloadContent will set our type to null; need to be sure to only set it to - // the real value on success - ObjectType newType = GetTypeOfContent(mContentType); - LOG(("OBJLC [%p]: OnStartRequest: Content Type=<%s> Old type=%u New Type=%u\n", - this, mContentType.get(), mType, newType)); - - // Now do a content policy check - // XXXbz this duplicates some code in nsContentBlocker::ShouldLoad - PRInt32 contentPolicyType; - switch (newType) { - case eType_Image: - contentPolicyType = nsIContentPolicy::TYPE_IMAGE; - break; - case eType_Document: - contentPolicyType = nsIContentPolicy::TYPE_SUBDOCUMENT; - break; - default: - contentPolicyType = nsIContentPolicy::TYPE_OBJECT; - break; - } - nsCOMPtr thisContent = - do_QueryInterface(static_cast(this)); - NS_ASSERTION(thisContent, "must be a content"); - - nsIDocument* doc = thisContent->OwnerDoc(); - - PRInt16 shouldProcess = nsIContentPolicy::ACCEPT; - rv = - NS_CheckContentProcessPolicy(contentPolicyType, - uri, - doc->NodePrincipal(), - static_cast(this), - mContentType, - nullptr, //extra - &shouldProcess, - nsContentUtils::GetContentPolicy(), - nsContentUtils::GetSecurityManager()); - if (NS_FAILED(rv) || NS_CP_REJECTED(shouldProcess)) { - HandleBeingBlockedByContentPolicy(rv, shouldProcess); - rv = NS_OK; // otherwise, the AutoFallback will make us fall back - return NS_BINDING_ABORTED; - } - - if (mType != newType) { - UnloadContent(); - } - - switch (newType) { - case eType_Image: - rv = LoadImageWithChannel(chan, getter_AddRefs(mFinalListener)); - NS_ENSURE_SUCCESS(rv, rv); - - // If we have a success result but no final listener, then the image is - // cached. In that case, we can just return: No need to try to call the - // final listener. - if (!mFinalListener) { - mType = newType; - return NS_BINDING_ABORTED; - } - break; - case eType_Document: { - if (!mFrameLoader) { - mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(), - mNetworkCreated); - if (!mFrameLoader) { - Fallback(false); - return NS_ERROR_UNEXPECTED; - } - } - - rv = mFrameLoader->CheckForRecursiveLoad(uri); - if (NS_FAILED(rv)) { - Fallback(false); - return rv; - } - - if (mType != newType) { - // XXX We must call this before getting the docshell to work around - // bug 300540; when that's fixed, this if statement can be removed. - mType = newType; - notifier.Notify(); - - if (!mFrameLoader) { - // mFrameLoader got nulled out when we notified, which most - // likely means the node was removed from the - // document. Abort the load that just started. - return NS_BINDING_ABORTED; - } - } - - // We're loading a document, so we have to set LOAD_DOCUMENT_URI - // (especially important for firing onload) - nsLoadFlags flags = 0; - chan->GetLoadFlags(&flags); - flags |= nsIChannel::LOAD_DOCUMENT_URI; - chan->SetLoadFlags(flags); - - nsCOMPtr docShell; - rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr req(do_QueryInterface(docShell)); - NS_ASSERTION(req, "Docshell must be an ifreq"); - - nsCOMPtr - uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - rv = uriLoader->OpenChannel(chan, nsIURILoader::DONT_RETARGET, req, - getter_AddRefs(mFinalListener)); - break; - } - case eType_Plugin: { - if (mType != newType) { - mType = newType; - notifier.Notify(); - } - nsCOMPtr pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); - nsPluginHost *pluginHost = static_cast(pluginHostCOM.get()); - if (!pluginHost) { - return NS_ERROR_NOT_AVAILABLE; - } - pluginHost->NewEmbeddedPluginStreamListener(uri, this, nullptr, - getter_AddRefs(mFinalListener)); - break; - } - case eType_Loading: - NS_NOTREACHED("Should not have a loading type here!"); - case eType_Null: - // Need to fallback here (instead of using the case below), so that we can - // set mFallbackReason without it being overwritten. This is also why we - // return early. - Fallback(false); - - PluginSupportState pluginState = GetPluginSupportState(thisContent, - mContentType); - // Do nothing, but fire the plugin not found event if needed - if (pluginState != ePluginOtherState) { - mFallbackReason = pluginState; - FirePluginError(thisContent, pluginState); - } - return NS_BINDING_ABORTED; - } - - if (mFinalListener) { - mType = newType; - - mSrcStreamLoading = true; - rv = mFinalListener->OnStartRequest(aRequest, aContext); - mSrcStreamLoading = false; - - if (NS_SUCCEEDED(rv)) { - // Plugins need to set up for NPRuntime. - if (mType == eType_Plugin) { - NotifyContentObjectWrapper(); - } - } else { - // Plugins don't fall back if there is an error here. - if (mType == eType_Plugin) { - rv = NS_OK; // this is necessary to avoid auto-fallback - return NS_BINDING_ABORTED; - } - Fallback(false); - } - - return rv; - } - - Fallback(false); - return NS_BINDING_ABORTED; + return LoadObject(true, false, aRequest); } NS_IMETHODIMP @@ -1053,10 +867,14 @@ nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest, } if (mFinalListener) { - return mFinalListener->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount); + return mFinalListener->OnDataAvailable(aRequest, aContext, aInputStream, + aOffset, aCount); } - // Abort this load if we have no listener here + // We shouldn't have a connected channel with no final listener + NS_NOTREACHED("Got data for channel with no connected final listener"); + mChannel = nullptr; + return NS_ERROR_UNEXPECTED; } @@ -1064,8 +882,7 @@ nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest, NS_IMETHODIMP nsObjectLoadingContent::GetFrameLoader(nsIFrameLoader** aFrameLoader) { - *aFrameLoader = mFrameLoader; - NS_IF_ADDREF(*aFrameLoader); + NS_IF_ADDREF(*aFrameLoader = mFrameLoader); return NS_OK; } @@ -1083,7 +900,6 @@ nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader) return NS_ERROR_NOT_IMPLEMENTED; } -// nsIObjectLoadingContent NS_IMETHODIMP nsObjectLoadingContent::GetActualType(nsACString& aType) { @@ -1101,24 +917,25 @@ nsObjectLoadingContent::GetDisplayedType(PRUint32* aType) NS_IMETHODIMP nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame) { - // Not having an instance yet is OK, but try to start one now that - // we have a frame. - if (!mInstanceOwner) { - AsyncStartPluginInstance(); - return NS_OK; + if (mType == eType_Plugin) { + if (!mInstanceOwner) { + // We have successfully set ourselves up in LoadObject, but not spawned an + // instance due to a lack of a frame. + AsyncStartPluginInstance(); + return NS_OK; + } + + // Disconnect any existing frame + DisconnectFrame(); + + // Set up relationship between instance owner and frame. + nsObjectFrame *objFrame = static_cast(aFrame); + mInstanceOwner->SetFrame(objFrame); + + // Set up new frame to draw. + objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size()); + objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf()); } - - // Disconnect any existing frame - DisconnectFrame(); - - // Set up relationship between instance owner and frame. - nsObjectFrame *objFrame = static_cast(aFrame); - mInstanceOwner->SetFrame(objFrame); - - // Set up new frame to draw. - objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size()); - objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf()); - return NS_OK; } @@ -1198,355 +1015,832 @@ nsObjectLoadingContent::ObjectState() const // plugins. return nsEventStates(); case eType_Null: - if (mSuppressed) - return NS_EVENT_STATE_SUPPRESSED; - if (mUserDisabled) - return NS_EVENT_STATE_USERDISABLED; - - // Otherwise, broken - nsEventStates state = NS_EVENT_STATE_BROKEN; - switch (mFallbackReason) { - case ePluginClickToPlay: + switch (mFallbackType) { + case eFallbackSuppressed: + return NS_EVENT_STATE_SUPPRESSED; + case eFallbackUserDisabled: + return NS_EVENT_STATE_USERDISABLED; + case eFallbackClickToPlay: return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY; - case ePluginVulnerableUpdatable: - return NS_EVENT_STATE_VULNERABLE_UPDATABLE; - case ePluginVulnerableNoUpdate: - return NS_EVENT_STATE_VULNERABLE_NO_UPDATE; - case ePluginDisabled: - state |= NS_EVENT_STATE_HANDLER_DISABLED; - break; - case ePluginBlocklisted: - state |= NS_EVENT_STATE_HANDLER_BLOCKED; - break; - case ePluginCrashed: - state |= NS_EVENT_STATE_HANDLER_CRASHED; - break; - case ePluginUnsupported: { + case eFallbackDisabled: + return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_DISABLED; + case eFallbackBlocklisted: + return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_BLOCKED; + case eFallbackCrashed: + return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_CRASHED; + case eFallbackUnsupported: { // Check to see if plugins are blocked on this platform. char* pluginsBlocked = PR_GetEnv("MOZ_PLUGINS_BLOCKED"); if (pluginsBlocked && pluginsBlocked[0] == '1') { - state |= NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM; + return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM; } else { - state |= NS_EVENT_STATE_TYPE_UNSUPPORTED; + return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_TYPE_UNSUPPORTED; } - break; } - case ePluginOutdated: - case ePluginOtherState: - // Do nothing, but avoid a compile warning - break; + case eFallbackOutdated: + case eFallbackAlternate: + return NS_EVENT_STATE_BROKEN; + case eFallbackVulnerableUpdatable: + return NS_EVENT_STATE_VULNERABLE_UPDATABLE; + case eFallbackVulnerableNoUpdate: + return NS_EVENT_STATE_VULNERABLE_NO_UPDATE; } - return state; }; NS_NOTREACHED("unknown type?"); - // this return statement only exists to avoid a compile warning - return nsEventStates(); + return NS_EVENT_STATE_LOADING; } -// -nsresult -nsObjectLoadingContent::LoadObject(const nsAString& aURI, - bool aNotify, - const nsCString& aTypeHint, - bool aForceLoad) +// Helper to call CheckURILoad on URI -> BaseURI and BaseURI -> Origin +bool nsObjectLoadingContent::CheckObjectURIs(PRInt16 *aContentPolicy, + PRInt32 aContentPolicyType) { - LOG(("OBJLC [%p]: Loading object: URI string=<%s> notify=%i type=<%s> forceload=%i\n", - this, NS_ConvertUTF16toUTF8(aURI).get(), aNotify, aTypeHint.get(), aForceLoad)); - - // Avoid StringToURI in order to use the codebase attribute as base URI - nsCOMPtr thisContent = + nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - NS_ASSERTION(thisContent, "must be a content"); + NS_ASSERTION(thisContent, "Must be an instance of content"); - nsIDocument* doc = thisContent->OwnerDoc(); - nsCOMPtr baseURI; - GetObjectBaseURI(thisContent, getter_AddRefs(baseURI)); + nsCOMPtr docBaseURI = thisContent->GetBaseURI(); - nsCOMPtr uri; - nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), - aURI, doc, - baseURI); - // If URI creation failed, fallback immediately - this only happens for - // malformed URIs - if (!uri) { - Fallback(aNotify); - return NS_OK; + // Must have these to load + if (!aContentPolicy || !mBaseURI) { + return false; } - NS_TryToSetImmutable(uri); - - return LoadObject(uri, aNotify, aTypeHint, aForceLoad); -} - -void -nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent, - AutoFallback& fallback, - const nsCString& aTypeHint) -{ - // Notify the UI and update the fallback state - PluginSupportState state = GetPluginSupportState(aContent, aTypeHint); - if (state != ePluginOtherState) { - fallback.SetPluginState(state); - FirePluginError(aContent, state); - } -} - -nsresult -nsObjectLoadingContent::LoadObject(nsIURI* aURI, - bool aNotify, - const nsCString& aTypeHint, - bool aForceLoad) -{ - // Only do a URI equality check for things that aren't stopped plugins. - // This is because we still need to load again if the plugin has been stopped. - if (mType == eType_Document || mType == eType_Image || mInstanceOwner) { - if (mURI && aURI) { - bool equal; - nsresult rv = mURI->Equals(aURI, &equal); - if (NS_SUCCEEDED(rv) && equal && !aForceLoad) { - // URI didn't change, do nothing - return NS_OK; - } - StopPluginInstance(); + bool ret; + if (!URIEquals(mBaseURI, docBaseURI)) { + // If our object sets a new baseURI, make sure that base URI could be + // loaded by the document + ret = CheckURILoad(mBaseURI, aContentPolicy, aContentPolicyType); + if (!ret) { + return false; } } - // Need to revoke any potentially pending instantiate events - if (mType == eType_Plugin && mPendingInstantiateEvent) { - mPendingInstantiateEvent = nullptr; + if (mURI) { + return CheckURILoad(mURI, aContentPolicy, aContentPolicyType); } - AutoNotifier notifier(this, aNotify); + return true; +} - mUserDisabled = mSuppressed = false; +bool nsObjectLoadingContent::CheckURILoad(nsIURI *aURI, + PRInt16 *aContentPolicy, + PRInt32 aContentPolicyType) +{ + nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); + NS_ASSERTION(secMan, "No security manager!?"); - mURI = aURI; - mContentType = aTypeHint; - - nsCOMPtr thisContent = + nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - NS_ASSERTION(thisContent, "must be a content"); + NS_ASSERTION(thisContent, "Must be an instance of content"); + + nsCOMPtr docBaseURI = thisContent->GetBaseURI(); nsIDocument* doc = thisContent->OwnerDoc(); - if (doc->IsBeingUsedAsImage()) { + nsresult rv = + secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0); + + if (NS_FAILED(rv)) { + nsCAutoString uri; + nsCAutoString baseUri; + aURI->GetSpec(uri); + aURI->GetSpec(baseUri); + LOG(("OBJLC [%p]: CheckLoadURIWithPrincipal denied load of %s (base %s)", + this, uri.get(), baseUri.get())); + return false; + } + + PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit + rv = NS_CheckContentLoadPolicy(aContentPolicyType, + aURI, + doc->NodePrincipal(), + static_cast(this), + mContentType, + nullptr, //extra + &shouldLoad, + nsContentUtils::GetContentPolicy(), + secMan); + NS_ENSURE_SUCCESS(rv, false); + if (aContentPolicy) { + *aContentPolicy = shouldLoad; + } + if (NS_CP_REJECTED(shouldLoad)) { + nsCAutoString uri; + nsCAutoString baseUri; + aURI->GetSpec(uri); + aURI->GetSpec(baseUri); + LOG(("OBJLC [%p]: Content policy denied load of %s (base %s)", + this, uri.get(), baseUri.get())); + return false; + } + return true; +} + +nsObjectLoadingContent::ParameterUpdateFlags +nsObjectLoadingContent::UpdateObjectParameters() +{ + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "Must be an instance of content"); + + PRUint32 caps = GetCapabilities(); + LOG(("OBJLC [%p]: Updating object parameters", this)); + + nsresult rv; + nsCAutoString newMime; + nsCOMPtr newURI; + nsCOMPtr newBaseURI; + ObjectType newType; + // Set if this state can't be used to load anything, forces eType_Null + bool stateInvalid = false; + // Indicates what parameters changed. + // eParamChannelChanged - means parameters that affect channel opening + // decisions changed + // eParamStateChanged - means anything that affects what content we load + // changed, even if the channel we'd open remains the + // same. + // + // State changes outside of the channel parameters only matter if we've + // already opened a channel or tried to instantiate content, whereas channel + // parameter changes require re-opening the channel even if we haven't gotten + // that far. + nsObjectLoadingContent::ParameterUpdateFlags retval = eParamNoChange; + + /// + /// Initial MIME Type + /// + if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) { + newMime.AssignLiteral("application/x-java-vm"); + } else { + nsAutoString typeAttr; + thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, typeAttr); + if (!typeAttr.IsEmpty()) { + CopyUTF16toUTF8(typeAttr, newMime); + } + } + + /// + /// classID + /// + + bool usingClassID = false; + if (caps & eSupportClassID) { + nsAutoString classIDAttr; + thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classIDAttr); + if (!classIDAttr.IsEmpty()) { + usingClassID = true; + if (NS_FAILED(TypeForClassID(classIDAttr, newMime))) { + // XXX(johns): Our de-facto behavior since forever was to refuse to load + // Objects who don't have a classid we support, regardless of other type + // or uri info leads to a valid plugin. + newMime.Assign(""); + stateInvalid = true; + } + } + } + + /// + /// Codebase + /// + + nsAutoString codebaseStr; + nsCOMPtr docBaseURI = thisContent->GetBaseURI(); + thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr); + if (codebaseStr.IsEmpty() && thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) { + // bug 406541 + // NOTE we send the full absolute URI resolved here to java in + // pluginInstanceOwner to avoid disagreements between parsing of + // relative URIs. We need to mimic java's quirks here to make that + // not break things. + codebaseStr.AssignLiteral("/"); // Java resolves codebase="" as "/" + // XXX(johns) This doesn't catch the case of "file:" which java would + // interpret as "file:///" but we would interpret as this document's URI + // but with a changed scheme. + } + + if (!codebaseStr.IsEmpty()) { + rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newBaseURI), + codebaseStr, + thisContent->OwnerDoc(), + docBaseURI); + if (NS_SUCCEEDED(rv)) { + NS_TryToSetImmutable(newBaseURI); + } else { + // Malformed URI + LOG(("OBJLC [%p]: Could not parse plugin's codebase as a URI, " + "will use document baseURI instead", this)); + } + } + + // Otherwise, use normal document baseURI + if (!newBaseURI) { + newBaseURI = docBaseURI; + } + + /// + /// URI + /// + + nsAutoString uriStr; + // Different elements keep this in various locations + if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) { + thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr); + } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) { + thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, uriStr); + } else if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) { + // Applet tags have no URI, and their 'code=' parameter is not parsed as one + } else { + NS_NOTREACHED("Unrecognized plugin-loading tag"); + } + + // Note that the baseURI changing could affect the newURI, even if uriStr did + // not change. + if (!uriStr.IsEmpty()) { + rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newURI), + uriStr, + thisContent->OwnerDoc(), + newBaseURI); + if (NS_SUCCEEDED(rv)) { + NS_TryToSetImmutable(newURI); + } else { + stateInvalid = true; + } + } + + /// + /// Check if the original (pre-channel) content-type or URI changed, and + /// record mOriginal{ContentType,URI} + /// + + if ((mOriginalContentType != newMime) || !URIEquals(mOriginalURI, newURI)) { + // These parameters changing requires re-opening the channel, so don't + // consider the currently-open channel below + // XXX(johns): Changing the mime type might change our decision on whether + // or not we load a channel, so we count changes to it as a + // channel parameter change for the sake of simplicity. + retval = (ParameterUpdateFlags)(retval | eParamChannelChanged); + LOG(("OBJLC [%p]: Channel parameters changed", this)); + } + mOriginalContentType = newMime; + mOriginalURI = newURI; + + /// + /// If we have a channel, see if its MIME type should take precendence and + /// check the final (redirected) URL + /// + + // If we have a loaded channel and channel parameters did not change, use it + // to determine what we would load. + bool useChannel = mChannelLoaded && !(retval & eParamChannelChanged); + if (mChannel && useChannel) { + nsCString channelType; + rv = mChannel->GetContentType(channelType); + if (NS_FAILED(rv)) { + NS_NOTREACHED("GetContentType failed"); + stateInvalid = true; + channelType.Assign(""); + } + + LOG(("OBJLC [%p]: Channel has a content type of %s", this, channelType.get())); + + bool binaryChannelType = false; + if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) { + channelType = APPLICATION_OCTET_STREAM; + mChannel->SetContentType(channelType); + binaryChannelType = true; + } else if (channelType.EqualsASCII(APPLICATION_OCTET_STREAM) + || channelType.EqualsASCII(BINARY_OCTET_STREAM)) { + binaryChannelType = true; + } + + // Channel can change our URI through redirection + rv = NS_GetFinalChannelURI(mChannel, getter_AddRefs(newURI)); + if (NS_FAILED(rv)) { + NS_NOTREACHED("NS_GetFinalChannelURI failure"); + stateInvalid = true; + } + + // The channel type overrides the guessed / provided type, except when: + // + // 1) If the channel returns a binary stream type, and we have a type hint + // for a non-document (we never want to display binary-as-document), + // use our type hint instead. + // 2) Our type hint is a type that we support with a plugin, ignore the + // server's type + // + // XXX(johns): HTML5's "typesmustmatch" attribute would need to be + // honored here if implemented + + ObjectType typeHint = newMime.IsEmpty() ? eType_Null : GetTypeOfContent(newMime); + + bool caseOne = binaryChannelType + && typeHint != eType_Null + && typeHint != eType_Document; + bool caseTwo = typeHint == eType_Plugin; + if (caseOne || caseTwo) { + // Set the type we'll use for dispatch on the channel. Otherwise we could + // end up trying to dispatch to a nsFrameLoader, which will complain that + // it couldn't find a way to handle application/octet-stream + nsCAutoString typeHint, dummy; + NS_ParseContentType(newMime, typeHint, dummy); + if (!typeHint.IsEmpty()) { + mChannel->SetContentType(typeHint); + } + } else if (binaryChannelType + && IsPluginEnabledByExtension(newURI, newMime)) { + mChannel->SetContentType(newMime); + } else { + newMime = channelType; + } + } + + bool isJava = nsPluginHost::IsJavaMIMEType(newMime.get()); + if (useChannel && (!mChannel || isJava)) { + // Sanity checks + // - Java does not load with a channel, and being java retroactively changes + // how we may have interpreted the codebase to construct this URI above. + // Because the behavior here is more or less undefined, play it safe and + // reject the load. + // + // - (useChannel && !mChannel) is true if a channel was opened but was + // subsequently invalidated + // in that case. + stateInvalid = true; + } + + /// + /// Determine final type + /// + // 1) If we have attempted channel load, or set stateInvalid above, the type + // is always null (fallback) + // 2) Otherwise, If we have a loaded channel, we grabbed its mimeType above, + // use that type. + // 3) Otherwise, See if we can load this as a plugin without a channel + // (image/document types always need a channel). + // - If we have indication this is a plugin (mime, extension, or classID) + // AND: + // - We have eAllowPluginSkipChannel OR + // - We have no URI in the first place OR + // - We're loading based on classID + // XXX(johns): Legacy behavior is to skip channel loading if we have + // a classID. I don't know why. + // 3) Otherwise, if we have a URI, set type to loading to indicate + // we'd need a channel to proceed. + // 4) Otherwise, type null to indicate unloadable content (fallback) + // + // XXX(johns): tags both support URIs and have + // eAllowPluginSkipChannel, meaning it is possible that we have a URI, but + // are not going to open a channel for it. The old objLC code did this (in a + // less obviously-intended way), so it's probably best not to change our + // behavior at this point. + // We ALSO skip channel loading for objects whose type is found by ClassID + // (We only support a tiny subset of classid: java and ActiveX, above) + // + + if (stateInvalid) { + newType = eType_Null; + } else if (useChannel) { + // If useChannel is set above, we considered it in setting newMime + newType = GetTypeOfContent(newMime); + LOG(("OBJLC [%p]: Using channel type", this)); + } else if (((caps & eAllowPluginSkipChannel) || !newURI || usingClassID) && + (GetTypeOfContent(newMime) == eType_Plugin)) { + newType = eType_Plugin; + LOG(("OBJLC [%p]: Skipping loading channel, type plugin", this)); + } else if (newURI) { + // We could potentially load this if we opened a channel on mURI, indicate + // This by leaving type as loading + newType = eType_Loading; + } else { + // Unloadable - no URI, and no plugin type. Non-plugin types (images, + // documents) always load with a channel. + newType = eType_Null; + } + + /// + /// Update changed values + /// + + if (newType != mType) { + retval = (ParameterUpdateFlags)(retval | eParamStateChanged); + LOG(("OBJLC [%p]: Type changed from %u -> %u", this, mType, newType)); + mType = newType; + } + + if (!URIEquals(mBaseURI, newBaseURI)) { + if (isJava) { + // Java bases its class loading on the base URI, so we consider the state + // to have changed if this changes. If the object is using a relative URI, + // mURI will have changed below regardless + retval = (ParameterUpdateFlags)(retval | eParamStateChanged); + } + LOG(("OBJLC [%p]: Object effective baseURI changed", this)); + mBaseURI = newBaseURI; + } + + if (!URIEquals(newURI, mURI)) { + retval = (ParameterUpdateFlags)(retval | eParamStateChanged); + LOG(("OBJLC [%p]: Object effective URI changed", this)); + mURI = newURI; + } + + if (mContentType != newMime) { + retval = (ParameterUpdateFlags)(retval | eParamStateChanged); + LOG(("OBJLC [%p]: Object effective mime type changed (%s -> %s)", this, mContentType.get(), newMime.get())); + mContentType = newMime; + } + + return retval; +} + +// Only OnStartRequest should be passing the channel parameter +nsresult +nsObjectLoadingContent::LoadObject(bool aNotify, + bool aForceLoad) +{ + return LoadObject(aNotify, aForceLoad, nullptr); +} + +nsresult +nsObjectLoadingContent::LoadObject(bool aNotify, + bool aForceLoad, + nsIRequest *aLoadingChannel) +{ + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); + nsIDocument* doc = thisContent->OwnerDoc(); + nsresult rv = NS_OK; + + // XXX(johns): In these cases, we refuse to touch our content and just + // remain unloaded, as per legacy behavior. It would make more sense to + // load fallback content initially and refuse to ever change state again. + if (doc->IsBeingUsedAsImage() || doc->IsLoadedAsData()) { return NS_OK; } - // From here on, we will always change the content. This means that a - // possibly-loading channel should be aborted. - if (mChannel) { - LOG(("OBJLC [%p]: Cancelling existing load\n", this)); + // Sanity check + if (!thisContent->IsInDoc()) { + NS_NOTREACHED("LoadObject called while not bound to a document"); + return NS_ERROR_UNEXPECTED; + } + LOG(("OBJLC [%p]: LoadObject called, notify %u, forceload %u, channel %p", + this, aNotify, aForceLoad, aLoadingChannel)); + + // We can't re-use an already open channel, but aForceLoad may make us try + // to load a plugin without any changes in channel state. + if (aForceLoad && mChannelLoaded) { + CloseChannel(); + mChannelLoaded = false; + } + + // Save these for NotifyStateChanged(); + nsEventStates oldState = ObjectState(); + ObjectType oldType = mType; + + ParameterUpdateFlags stateChange = UpdateObjectParameters(); + + if (!stateChange && !aForceLoad) { + return NS_OK; + } + + /// + /// State has changed, unload existing content and attempt to load new type + /// + LOG(("OBJLC [%p]: LoadObject - plugin state changed (%u)", + this, stateChange)); + + // Setup fallback info. We may also change type to fallback below in case of + // sanity/OOM/etc. errors. We default to showing alternate content + // NOTE LoadFallback can override this in some cases + FallbackType fallbackType = eFallbackAlternate; + + if (mType == eType_Null) { + nsresult pluginsupport = IsPluginEnabledForType(mContentType); + if (pluginsupport == NS_ERROR_PLUGIN_DISABLED) { + fallbackType = eFallbackDisabled; + } else if (pluginsupport == NS_ERROR_PLUGIN_BLOCKLISTED) { + fallbackType = eFallbackBlocklisted; + } else { + fallbackType = eFallbackUnsupported; + } + } + + // We synchronously start/stop plugin instances below, which may spin the + // event loop. Re-entering into the load is fine, but at that point the + // original load call needs to abort when unwinding + // NOTE this is located *after* the state change check, a subseqent load + // with no subsequently changed state will be a no-op. + mIsLoading = true; + AutoSetLoadingToFalse reentryCheck(this); + + // Unload existing content, keeping in mind stopping plugins might spin the + // event loop. Note that we check for still-open channels below + UnloadObject(false); // Don't reset state + if (!mIsLoading) { + // The event loop must've spun and re-entered into LoadObject, which + // finished the load + return NS_OK; + } + + if (stateChange & eParamChannelChanged) { + // If the channel params changed, throw away the channel, but unset + // mChannelLoaded so we'll still try to open a new one for this load if + // necessary + CloseChannel(); + mChannelLoaded = false; + } else if (mType == eType_Null && mChannel) { + // If we opened a channel but then failed to find a loadable state, throw it + // away. mChannelLoaded will indicate that we tried to load a channel at one + // point so we wont recurse + CloseChannel(); + } else if (mChannelLoaded && mChannel != aLoadingChannel) { + // The only time we should have a loaded channel with a changed state is + // when the channel has just opened -- in which case this call should + // have originated from OnStartRequest + NS_NOTREACHED("Loading with a channel, but state doesn't make sense"); + return NS_OK; + } + + // + // Security checks + // + + // NOTE For eType_Loading we'll try all three types, as we want to go ahead + // with the channel if it could be any acceptable type. This type is + // passed to OpenChannel() as the LoadType. We pass through LoadObject + // again once the channel is opened and we're actually loading, so if + // the final URI doesn't pass the now-known type, we'll abort. + PRInt32 policyType; + if (mType != eType_Null) { + bool allowLoad = false; + PRInt16 contentPolicy = nsIContentPolicy::ACCEPT; + PRUint32 caps = GetCapabilities(); + bool supportImage = caps & eSupportImages; + bool supportDoc = (caps & eSupportDocuments) || (caps & eSupportSVG); + bool supportPlugin = caps & eSupportPlugins; + if (mType == eType_Image || (mType == eType_Loading && supportImage)) { + policyType = nsIContentPolicy::TYPE_IMAGE; + allowLoad = CheckObjectURIs(&contentPolicy, policyType); + } + if (!allowLoad && + (mType == eType_Document || (mType == eType_Loading && supportDoc))) { + contentPolicy = nsIContentPolicy::ACCEPT; + policyType = nsIContentPolicy::TYPE_SUBDOCUMENT; + allowLoad = CheckObjectURIs(&contentPolicy, policyType); + } + if (!allowLoad && + (mType == eType_Plugin || (mType == eType_Loading && supportPlugin))) { + contentPolicy = nsIContentPolicy::ACCEPT; + policyType = nsIContentPolicy::TYPE_OBJECT; + allowLoad = CheckObjectURIs(&contentPolicy, policyType); + } + + // Load denied, switch to fallback and set disabled/suppressed if applicable + if (!allowLoad) { + mType = eType_Null; + if (contentPolicy == nsIContentPolicy::REJECT_TYPE) { + fallbackType = eFallbackUserDisabled; + } else { + fallbackType = eFallbackSuppressed; + } + } + } + + // If we're a plugin but shouldn't start yet, load fallback with + // reason click-to-play instead + FallbackType clickToPlayReason; + if (mType == eType_Plugin && !ShouldPlay(clickToPlayReason)) { + LOG(("OBJLC [%p]: Marking plugin as click-to-play", this)); + mType = eType_Null; + fallbackType = clickToPlayReason; + } + + // Sanity check: We shouldn't have any loaded resources, pending events, or + // a final listener at this point + if (mFrameLoader || mPendingInstantiateEvent || mInstanceOwner || + mFinalListener) + { + NS_NOTREACHED("Trying to load new plugin with existing content"); + rv = NS_ERROR_UNEXPECTED; + return NS_OK; + } + + // More sanity-checking: + // If mChannel is set, mChannelLoaded should be set, and vice-versa + if (mType != eType_Null && !!mChannel != mChannelLoaded) { + NS_NOTREACHED("Trying to load with bad channel state"); + rv = NS_ERROR_UNEXPECTED; + return NS_OK; + } + + /// + /// Attempt to load new type + /// + switch (mType) { + case eType_Image: + if (!mChannel) { + // We have a LoadImage() call, but UpdateObjectParameters requires a + // channel for images, so this is not a valid state. + NS_NOTREACHED("Attempting to load image without a channel?"); + rv = NS_ERROR_UNEXPECTED; + break; + } + rv = LoadImageWithChannel(mChannel, getter_AddRefs(mFinalListener)); + if (mFinalListener) { + // Note that LoadObject is called from mChannel's OnStartRequest + // when loading with a channel + mSrcStreamLoading = true; + rv = mFinalListener->OnStartRequest(mChannel, nullptr); + mSrcStreamLoading = false; + } + break; + case eType_Plugin: + { + if (mChannel) { + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); + if (!pluginHost) { + NS_NOTREACHED("No pluginHost"); + rv = NS_ERROR_UNEXPECTED; + break; + } + + // Force a sync state change now, we need the frame created + NotifyStateChanged(oldType, oldState, true, aNotify); + oldType = mType; + oldState = ObjectState(); + + rv = pluginHost->NewEmbeddedPluginStreamListener(mURI, this, nullptr, + getter_AddRefs(mFinalListener)); + if (NS_SUCCEEDED(rv)) { + // Note that LoadObject is called from mChannel's OnStartRequest + // when loading with a channel + + mSrcStreamLoading = true; + rv = mFinalListener->OnStartRequest(mChannel, nullptr); + mSrcStreamLoading = false; + if (NS_SUCCEEDED(rv)) { + NotifyContentObjectWrapper(); + } + } + } else { + rv = AsyncStartPluginInstance(); + } + } + break; + case eType_Document: + { + if (!mChannel) { + // We could mFrameLoader->LoadURI(mURI), but UpdateObjectParameters + // requires documents have a channel, so this is not a valid state. + NS_NOTREACHED("Attempting to load a document without a channel"); + mType = eType_Null; + break; + } + if (!mFrameLoader) { + // Force a sync state change, we need the frame created + NotifyStateChanged(oldType, oldState, true, aNotify); + oldType = mType; + oldState = ObjectState(); + + mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(), + mNetworkCreated); + if (!mFrameLoader) { + NS_NOTREACHED("nsFrameLoader::Create failed"); + mType = eType_Null; + break; + } + } + + rv = mFrameLoader->CheckForRecursiveLoad(mURI); + if (NS_FAILED(rv)) { + mType = eType_Null; + break; + } + + // We're loading a document, so we have to set LOAD_DOCUMENT_URI + // (especially important for firing onload) + nsLoadFlags flags = 0; + mChannel->GetLoadFlags(&flags); + flags |= nsIChannel::LOAD_DOCUMENT_URI; + mChannel->SetLoadFlags(flags); + + nsCOMPtr docShell; + rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell)); + if (NS_FAILED(rv)) { + NS_NOTREACHED("Could not get DocShell from mFrameLoader?"); + mType = eType_Null; + break; + } + + nsCOMPtr req(do_QueryInterface(docShell)); + NS_ASSERTION(req, "Docshell must be an ifreq"); + + nsCOMPtr + uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID, &rv)); + if (NS_FAILED(rv)) { + NS_NOTREACHED("Failed to get uriLoader service"); + mType = eType_Null; + break; + } + rv = uriLoader->OpenChannel(mChannel, nsIURILoader::DONT_RETARGET, req, + getter_AddRefs(mFinalListener)); + if (NS_SUCCEEDED(rv)) { + // Note that LoadObject is called from mChannel's OnStartRequest + // when loading with a channel + mSrcStreamLoading = true; + rv = mFinalListener->OnStartRequest(mChannel, nullptr); + mSrcStreamLoading = false; + } + } + break; + case eType_Loading: + // If our type remains Loading, we need a channel to proceed + rv = OpenChannel(policyType); + if (NS_FAILED(rv)) { + LOG(("OBJLC [%p]: OpenChannel returned failure (%u)", this, rv)); + } + break; + case eType_Null: + // Handled below, silence compiler warnings + break; + }; + + if (NS_FAILED(rv)) { + // If we failed in the loading hunk above, switch to fallback + LOG(("OBJLC [%p]: Loading failed, switching to fallback", this)); + mType = eType_Null; + } + + // Switching to fallback state + if (mType == eType_Null) { + LOG(("OBJLC [%p]: Loading fallback, type %u", this, fallbackType)); + NS_ASSERTION(!mFrameLoader && !mInstanceOwner, + "switched to type null but also loaded something"); + + if (mChannel) { + // If we were loading with a channel but then failed over, throw it away + // (this also closes mFinalListener) + CloseChannel(); + } + + // Don't notify or send events - we'll handle those ourselves + // (so really this is just setting mFallbackType) + LoadFallback(fallbackType, false); + } + + // Notify of our final state if we haven't already + NotifyStateChanged(oldType, oldState, false, aNotify); + + if (mType == eType_Null && mFallbackType != eFallbackAlternate) { + // if we're not showing alternate content, fire a pluginerror to trigger + // (we stopped LoadFallback from doing so above, it doesn't know of our old + // state) + FirePluginError(mFallbackType); + } + + return NS_OK; +} + +nsresult +nsObjectLoadingContent::CloseChannel() +{ + if (mChannel) { + LOG(("OBJLC [%p]: Closing channel\n", this)); // These three statements are carefully ordered: // - onStopRequest should get a channel whose status is the same as the // status argument // - onStopRequest must get a non-null channel mChannel->Cancel(NS_BINDING_ABORTED); if (mFinalListener) { - // NOTE: Since mFinalListener is only set in onStartRequest, which takes - // care of calling mFinalListener->OnStartRequest, mFinalListener is only - // non-null here if onStartRequest was already called. + // NOTE mFinalListener is only created when we load with a channel, which + // LoadObject() requires come from a OnStartRequest call mFinalListener->OnStopRequest(mChannel, nullptr, NS_BINDING_ABORTED); mFinalListener = nullptr; } mChannel = nullptr; } + return NS_OK; +} - // Security checks - if (doc->IsLoadedAsData()) { - if (!doc->IsStaticDocument()) { - Fallback(false); - } - return NS_OK; - } +nsresult +nsObjectLoadingContent::OpenChannel(PRInt32 aPolicyType) +{ + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); + nsIDocument* doc = thisContent->OwnerDoc(); + NS_ASSERTION(doc, "No owner document?"); + NS_ASSERTION(!mInstanceOwner && !mInstantiating, + "opening a new channel with already loaded content"); - // Can't do security checks without a URI - hopefully the plugin will take - // care of that - // Null URIs happen when the URL to load is specified via other means than the - // data/src attribute, for example via custom elements. - if (aURI) { - nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); - NS_ASSERTION(secMan, "No security manager!?"); - nsresult rv = - secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0); - if (NS_FAILED(rv)) { - Fallback(false); - return NS_OK; - } - - PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit - rv = - NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT, - aURI, - doc->NodePrincipal(), - static_cast(this), - aTypeHint, - nullptr, //extra - &shouldLoad, - nsContentUtils::GetContentPolicy(), - secMan); - if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { - HandleBeingBlockedByContentPolicy(rv, shouldLoad); - return NS_OK; - } - } - - nsresult rv = NS_ERROR_UNEXPECTED; - // This fallback variable MUST be declared after the notifier variable. Do NOT - // change the order of the declarations! - AutoFallback fallback(this, &rv); - - PRUint32 caps = GetCapabilities(); - LOG(("OBJLC [%p]: Capabilities: %04x\n", this, caps)); - - nsCAutoString overrideType; - if ((caps & eOverrideServerType) && - ((!aTypeHint.IsEmpty() && NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) || - (aURI && IsPluginEnabledByExtension(aURI, overrideType)))) { - ObjectType newType; - if (overrideType.IsEmpty()) { - newType = GetTypeOfContent(aTypeHint); - } else { - mContentType = overrideType; - newType = eType_Plugin; - } - - if (newType != mType) { - LOG(("OBJLC [%p]: (eOverrideServerType) Changing type from %u to %u\n", this, mType, newType)); - - UnloadContent(); - - // Must have a frameloader before creating a frame, or the frame will - // create its own. - if (!mFrameLoader && newType == eType_Document) { - mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(), - mNetworkCreated); - if (!mFrameLoader) { - mURI = nullptr; - return NS_OK; - } - } - - // Must notify here for plugins - // If aNotify is false, we'll just wait until we get a frame and use the - // async instantiate path. - // XXX is this still needed? (for documents?) - mType = newType; - if (aNotify) - notifier.Notify(); - } - switch (newType) { - case eType_Image: - // Don't notify, because we will take care of that ourselves. - if (aURI) { - rv = LoadImage(aURI, aForceLoad, false); - } else { - rv = NS_ERROR_NOT_AVAILABLE; - } - break; - case eType_Plugin: - rv = AsyncStartPluginInstance(); - break; - case eType_Document: - if (aURI) { - rv = mFrameLoader->LoadURI(aURI); - } else { - rv = NS_ERROR_NOT_AVAILABLE; - } - break; - case eType_Loading: - NS_NOTREACHED("Should not have a loading type here!"); - case eType_Null: - // No need to load anything, notify of the failure. - UpdateFallbackState(thisContent, fallback, aTypeHint); - break; - }; - return NS_OK; - } - - // If the class ID specifies a supported plugin, or if we have no explicit URI - // but a type, immediately instantiate the plugin. - bool isSupportedClassID = false; - nsCAutoString typeForID; // Will be set iff isSupportedClassID == true - bool hasID = false; - if (caps & eSupportClassID) { - nsAutoString classid; - thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classid); - if (!classid.IsEmpty()) { - hasID = true; - isSupportedClassID = NS_SUCCEEDED(TypeForClassID(classid, typeForID)); - } - } - - if (hasID && !isSupportedClassID) { - // We have a class ID and it's unsupported. Fallback in that case. - rv = NS_ERROR_NOT_AVAILABLE; - return NS_OK; - } - - if (isSupportedClassID || - (!aURI && !aTypeHint.IsEmpty() && - GetTypeOfContent(aTypeHint) == eType_Plugin)) { - // No URI, but we have a type. The plugin will handle the load. - // Or: supported class id, plugin will handle the load. - mType = eType_Plugin; - - // At this point, the stored content type - // must be equal to our type hint. Similar, - // our URI must be the requested URI. - // (->Equals would suffice, but == is cheaper - // and handles NULL) - NS_ASSERTION(mContentType.Equals(aTypeHint), "mContentType wrong!"); - NS_ASSERTION(mURI == aURI, "mURI wrong!"); - - if (isSupportedClassID) { - // Use the classid's type - NS_ASSERTION(!typeForID.IsEmpty(), "Must have a real type!"); - mContentType = typeForID; - // XXX(biesi). The plugin instantiation code used to pass the base URI - // here instead of the plugin URI for instantiation via class ID, so I - // continue to do so. Why that is, no idea... - GetObjectBaseURI(thisContent, getter_AddRefs(mURI)); - if (!mURI) { - mURI = aURI; - } - } - - // rv is references by a stack-based object, need to assign here - rv = AsyncStartPluginInstance(); - - return rv; - } - - if (!aURI) { - // No URI and if we have got this far no enabled plugin supports the type - rv = NS_ERROR_NOT_AVAILABLE; - - // We should only notify the UI if there is at least a type to go on for - // finding a plugin to use, unless it's a supported image or document type. - if (!aTypeHint.IsEmpty() && GetTypeOfContent(aTypeHint) == eType_Null) { - UpdateFallbackState(thisContent, fallback, aTypeHint); - } - - return NS_OK; - } + nsresult rv; + mChannel = nullptr; // E.g. mms:// - if (!CanHandleURI(aURI)) { - if (aTypeHint.IsEmpty()) { - rv = NS_ERROR_NOT_AVAILABLE; - return NS_OK; - } - - if (NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) { - mType = eType_Plugin; - } else { - rv = NS_ERROR_NOT_AVAILABLE; - // No plugin to load, notify of the failure. - UpdateFallbackState(thisContent, fallback, aTypeHint); - } - - return NS_OK; + if (!mURI || !CanHandleURI(mURI)) { + return NS_ERROR_NOT_AVAILABLE; } nsCOMPtr group = doc->GetDocumentLoadGroup(); @@ -1558,9 +1852,9 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI, if (csp) { channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); channelPolicy->SetContentSecurityPolicy(csp); - channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT); + channelPolicy->SetLoadType(aPolicyType); } - rv = NS_NewChannel(getter_AddRefs(chan), aURI, nullptr, group, this, + rv = NS_NewChannel(getter_AddRefs(chan), mURI, nullptr, group, this, nsIChannel::LOAD_CALL_CONTENT_SNIFFERS | nsIChannel::LOAD_CLASSIFY_URI, channelPolicy); @@ -1572,35 +1866,21 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI, httpChan->SetReferrer(doc->GetDocumentURI()); } - // MIME Type hint - if (!aTypeHint.IsEmpty()) { - nsCAutoString typeHint, dummy; - NS_ParseContentType(aTypeHint, typeHint, dummy); - if (!typeHint.IsEmpty()) { - chan->SetContentType(typeHint); - } - } - // Set up the channel's principal and such, like nsDocShell::DoURILoad does nsContentUtils::SetUpChannelOwner(thisContent->NodePrincipal(), - chan, aURI, true); + chan, mURI, true); nsCOMPtr scriptChannel = do_QueryInterface(chan); if (scriptChannel) { // Allow execution against our context if the principals match - scriptChannel-> - SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); + scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); } // AsyncOpen can fail if a file does not exist. - // Show fallback content in that case. rv = chan->AsyncOpen(this, nullptr); - if (NS_SUCCEEDED(rv)) { - LOG(("OBJLC [%p]: Channel opened.\n", this)); - - mChannel = chan; - mType = eType_Loading; - } + NS_ENSURE_SUCCESS(rv, rv); + LOG(("OBJLC [%p]: Channel opened", this)); + mChannel = chan; return NS_OK; } @@ -1614,38 +1894,14 @@ nsObjectLoadingContent::GetCapabilities() const } void -nsObjectLoadingContent::Fallback(bool aNotify) -{ - AutoNotifier notifier(this, aNotify); - - UnloadContent(); -} - -void -nsObjectLoadingContent::RemovedFromDocument() +nsObjectLoadingContent::DestroyContent() { if (mFrameLoader) { - // XXX This is very temporary and must go away mFrameLoader->Destroy(); mFrameLoader = nullptr; - - // Clear the current URI, so that LoadObject doesn't think that we - // have already loaded the content. - mURI = nullptr; } - // When a plugin instance node is removed from the document we'll - // let the plugin continue to run at least until we get back to - // the event loop. If we get back to the event loop and the node - // has still not been added back to the document then we stop - // the plugin. - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); - nsCOMPtr event = new InDocCheckEvent(thisContent); - - nsCOMPtr appShell = do_GetService(kAppShellCID); - if (appShell) { - appShell->RunInStableState(event); - } + StopPluginInstance(); } /* static */ @@ -1657,109 +1913,24 @@ nsObjectLoadingContent::Traverse(nsObjectLoadingContent *tmp, cb.NoteXPCOMChild(static_cast(tmp->mFrameLoader)); } -// -/* static */ bool -nsObjectLoadingContent::IsSuccessfulRequest(nsIRequest* aRequest) -{ - nsresult status; - nsresult rv = aRequest->GetStatus(&status); - if (NS_FAILED(rv) || NS_FAILED(status)) { - return false; - } - - // This may still be an error page or somesuch - nsCOMPtr httpChan(do_QueryInterface(aRequest)); - if (httpChan) { - bool success; - rv = httpChan->GetRequestSucceeded(&success); - if (NS_FAILED(rv) || !success) { - return false; - } - } - - // Otherwise, the request is successful - return true; -} - -/* static */ bool -nsObjectLoadingContent::CanHandleURI(nsIURI* aURI) -{ - nsCAutoString scheme; - if (NS_FAILED(aURI->GetScheme(scheme))) { - return false; - } - - nsIIOService* ios = nsContentUtils::GetIOService(); - if (!ios) - return false; - - nsCOMPtr handler; - ios->GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); - if (!handler) { - return false; - } - - nsCOMPtr extHandler = - do_QueryInterface(handler); - // We can handle this URI if its protocol handler is not the external one - return extHandler == nullptr; -} - -bool -nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType) -{ - nsCOMPtr thisContent = - do_QueryInterface(static_cast(this)); - NS_ASSERTION(thisContent, "must be a content"); - - nsresult rv; - nsCOMPtr info( - do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv)); - PRUint32 supported; - if (info) { - nsCOMPtr webNav; - nsIDocument* currentDoc = thisContent->GetCurrentDoc(); - if (currentDoc) { - webNav = do_GetInterface(currentDoc->GetScriptGlobalObject()); - } - rv = info->IsTypeSupported(aMimeType, webNav, &supported); - } - - if (NS_SUCCEEDED(rv)) { - if (supported == nsIWebNavigationInfo::UNSUPPORTED) { - // Try a stream converter - // NOTE: We treat any type we can convert from as a supported type. If a - // type is not actually supported, the URI loader will detect that and - // return an error, and we'll fallback. - nsCOMPtr convServ = - do_GetService("@mozilla.org/streamConverters;1"); - bool canConvert = false; - if (convServ) { - rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert); - } - - return NS_SUCCEEDED(rv) && canConvert; - } - - // Don't want to support plugins as documents - return supported != nsIWebNavigationInfo::PLUGIN; - } - - return false; -} - void -nsObjectLoadingContent::UnloadContent() +nsObjectLoadingContent::UnloadObject(bool aResetState) { - // Don't notify in CancelImageRequests. We do it ourselves. + // Don't notify in CancelImageRequests until we transition to a new loaded + // state CancelImageRequests(false); if (mFrameLoader) { mFrameLoader->Destroy(); mFrameLoader = nullptr; } - mType = eType_Null; - mUserDisabled = mSuppressed = false; - mFallbackReason = ePluginOtherState; + + if (aResetState) { + CloseChannel(); + mType = eType_Loading; + } + + // This call should be last as it may re-enter + StopPluginInstance(); } void @@ -1768,9 +1939,9 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType, bool aSync, bool aNotify) { - LOG(("OBJLC [%p]: Notifying about state change: (%u, %llx) -> (%u, %llx) (sync=%i)\n", - this, aOldType, aOldState.GetInternalValue(), mType, - ObjectState().GetInternalValue(), aSync)); + LOG(("OBJLC [%p]: Notifying about state change: (%u, %llx) -> (%u, %llx)" + " (sync %i, notify %i)", this, aOldType, aOldState.GetInternalValue(), + mType, ObjectState().GetInternalValue(), aSync, aNotify)); nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); @@ -1778,6 +1949,8 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType, NS_ASSERTION(thisContent->IsElement(), "Not an element?"); + // XXX(johns): A good bit of the code below replicates UpdateState(true) + // Unfortunately, we do some state changes without notifying // (e.g. in Fallback when canceling image requests), so we have to // manually notify object state changes. @@ -1818,14 +1991,17 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType, } } -/* static */ void -nsObjectLoadingContent::FirePluginError(nsIContent* thisContent, - PluginSupportState state) +void +nsObjectLoadingContent::FirePluginError(FallbackType aFallbackType) { - LOG(("OBJLC []: Dispatching nsPluginErrorEvent for content %p\n", - thisContent)); + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); - nsCOMPtr ev = new nsPluginErrorEvent(thisContent, state); + LOG(("OBJLC [%p]: Dispatching nsPluginErrorEvent for content %p\n", + this)); + + nsCOMPtr ev = new nsPluginErrorEvent(thisContent, aFallbackType); nsresult rv = NS_DispatchToCurrentThread(ev); if (NS_FAILED(rv)) { NS_WARNING("failed to dispatch nsPluginErrorEvent"); @@ -1835,16 +2011,20 @@ nsObjectLoadingContent::FirePluginError(nsIContent* thisContent, nsObjectLoadingContent::ObjectType nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType) { + if (aMIMEType.IsEmpty()) { + return eType_Null; + } + PRUint32 caps = GetCapabilities(); if ((caps & eSupportImages) && IsSupportedImage(aMIMEType)) { return eType_Image; } + // SVGs load as documents, but are their own capability bool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml"); - bool supportedSVG = isSVG && (caps & eSupportSVG); - if (((caps & eSupportDocuments) || supportedSVG) && - IsSupportedDocument(aMIMEType)) { + bool supportType = isSVG ? eSupportSVG : eSupportDocuments; + if ((caps & supportType) && IsSupportedDocument(aMIMEType)) { return eType_Document; } @@ -1883,27 +2063,6 @@ nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID, return NS_ERROR_NOT_AVAILABLE; } -void -nsObjectLoadingContent::GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI) -{ - // We want to use swap(); since this is just called from this file, - // we can assert this (callers use comptrs) - NS_PRECONDITION(*aURI == nullptr, "URI must be inited to zero"); - - // For plugins, the codebase attribute is the base URI - nsCOMPtr baseURI = thisContent->GetBaseURI(); - nsAutoString codebase; - thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, - codebase); - if (!codebase.IsEmpty()) { - nsContentUtils::NewURIWithDocumentCharset(aURI, codebase, - thisContent->OwnerDoc(), - baseURI); - } else { - baseURI.swap(*aURI); - } -} - nsObjectFrame* nsObjectLoadingContent::GetExistingFrame() { @@ -1913,94 +2072,6 @@ nsObjectLoadingContent::GetExistingFrame() return static_cast(objFrame); } -void -nsObjectLoadingContent::HandleBeingBlockedByContentPolicy(nsresult aStatus, - PRInt16 aRetval) -{ - // Must call UnloadContent first, as it overwrites - // mSuppressed/mUserDisabled. It also takes care of setting the type to - // eType_Null. - UnloadContent(); - if (NS_SUCCEEDED(aStatus)) { - if (aRetval == nsIContentPolicy::REJECT_TYPE) { - mUserDisabled = true; - } else if (aRetval == nsIContentPolicy::REJECT_SERVER) { - mSuppressed = true; - } - } -} - -PluginSupportState -nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent, - const nsCString& aContentType) -{ - if (!aContent->IsHTML()) { - return ePluginOtherState; - } - - if (aContent->Tag() == nsGkAtoms::embed || - aContent->Tag() == nsGkAtoms::applet) { - return GetPluginDisabledState(aContentType); - } - - bool hasAlternateContent = false; - - // Search for a child with a pluginurl name - for (nsIContent* child = aContent->GetFirstChild(); - child; - child = child->GetNextSibling()) { - if (child->IsHTML(nsGkAtoms::param)) { - if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, - NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) { - return GetPluginDisabledState(aContentType); - } - } else if (!hasAlternateContent) { - hasAlternateContent = - nsStyleUtil::IsSignificantChild(child, true, false); - } - } - - PluginSupportState pluginDisabledState = GetPluginDisabledState(aContentType); - if (pluginDisabledState == ePluginClickToPlay || - pluginDisabledState == ePluginVulnerableUpdatable || - pluginDisabledState == ePluginVulnerableNoUpdate) { - return pluginDisabledState; - } else if (hasAlternateContent) { - return ePluginOtherState; - } else { - return pluginDisabledState; - } -} - -PluginSupportState -nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType) -{ - nsresult rv = IsPluginEnabledForType(aContentType); - if (rv == NS_ERROR_PLUGIN_DISABLED) { - return ePluginDisabled; - } - if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY) { - PRUint32 state; - nsCOMPtr pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); - nsPluginHost *pluginHost = static_cast(pluginHostCOM.get()); - if (pluginHost) { - rv = pluginHost->GetBlocklistStateForType(aContentType.get(), &state); - if (NS_SUCCEEDED(rv)) { - if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) { - return ePluginVulnerableUpdatable; - } else if (state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) { - return ePluginVulnerableNoUpdate; - } - } - } - return ePluginClickToPlay; - } - if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) { - return ePluginBlocklisted; - } - return ePluginUnsupported; -} - void nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const { @@ -2038,10 +2109,19 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag, const nsAString& browserDumpID, bool submittedCrashReport) { - AutoNotifier notifier(this, true); - UnloadContent(); - mFallbackReason = ePluginCrashed; - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + LOG(("OBJLC [%p]: Plugin Crashed, queuing crash event", this)); + NS_ASSERTION(mType == eType_Plugin, "PluginCrashed at non-plugin type"); + + // Instance is dead, clean up + mInstanceOwner = nullptr; + CloseChannel(); + + // Switch to fallback/crashed state, notify + LoadFallback(eFallbackCrashed, true); + + // send nsPluginCrashedEvent + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); // Note that aPluginTag in invalidated after we're called, so copy // out any data we need now. @@ -2050,12 +2130,13 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag, nsCAutoString pluginFilename; aPluginTag->GetFilename(pluginFilename); - nsCOMPtr ev = new nsPluginCrashedEvent(thisContent, - pluginDumpID, - browserDumpID, - NS_ConvertUTF8toUTF16(pluginName), - NS_ConvertUTF8toUTF16(pluginFilename), - submittedCrashReport); + nsCOMPtr ev = + new nsPluginCrashedEvent(thisContent, + pluginDumpID, + browserDumpID, + NS_ConvertUTF8toUTF16(pluginName), + NS_ConvertUTF8toUTF16(pluginFilename), + submittedCrashReport); nsresult rv = NS_DispatchToCurrentThread(ev); if (NS_FAILED(rv)) { NS_WARNING("failed to dispatch nsPluginCrashedEvent"); @@ -2079,7 +2160,7 @@ nsObjectLoadingContent::SyncStartPluginInstance() nsCOMPtr kungFuURIGrip(mURI); nsCString contentType(mContentType); - return InstantiatePluginInstance(contentType.get(), mURI.get()); + return InstantiatePluginInstance(); } NS_IMETHODIMP @@ -2129,7 +2210,7 @@ DoDelayedStop(nsPluginInstanceOwner* aInstanceOwner, if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash")) return false; #endif - + // Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524), // XStandard (bug 430219), CMISS Zinc (bug 429604). if (aDelayedStop @@ -2148,6 +2229,81 @@ DoDelayedStop(nsPluginInstanceOwner* aInstanceOwner, return false; } +void +nsObjectLoadingContent::LoadFallback(FallbackType aType, bool aNotify) { + nsEventStates oldState = ObjectState(); + ObjectType oldType = mType; + + NS_ASSERTION(!mInstanceOwner && !mFrameLoader && !mChannel, + "LoadFallback called with loaded content"); + + // + // Fixup mFallbackType + // + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); + NS_ASSERTION(thisContent, "must be a content"); + + if (!thisContent->IsHTML()) { + // Don't let custom fallback handlers run outside HTML + LOG(("OBJLC [%p]: Non-HTML content, forcing eFallbackAlternate", this)); + aType = eFallbackAlternate; + } + + /// XXX(johns): This block is just mimicing legacy behavior, not any spec + // Check if we have any significant content (excluding param tags) OR a + // param named 'pluginUrl' + bool hasAlternateContent = false; + bool hasPluginUrl = false; + if (thisContent->Tag() == nsGkAtoms::object && + (aType == eFallbackUnsupported || + aType == eFallbackDisabled || + aType == eFallbackBlocklisted)) + { + for (nsIContent* child = thisContent->GetFirstChild(); + child; child = child->GetNextSibling()) + { + if (child->IsHTML(nsGkAtoms::param)) { + if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, + NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) { + hasPluginUrl = true; + } + } else if (nsStyleUtil::IsSignificantChild(child, true, false)) { + hasAlternateContent = true; + } + } + + // Show alternate content if it exists, unless we have a 'pluginurl' param, + // in which case the missing-plugin fallback handler will want to handle + // it + if (hasAlternateContent && !hasPluginUrl) { + LOG(("OBJLC [%p]: Unsupported/disabled/blocked plugin has alternate " + "content, showing instead of custom handler", this)); + aType = eFallbackAlternate; + } + } + + mType = eType_Null; + mFallbackType = aType; + + // + // Notify & send events + // + if (!aNotify) { + return; // done + } + + NotifyStateChanged(oldType, oldState, false, true); + + if (mFallbackType != eFallbackCrashed && + mFallbackType != eFallbackAlternate) + { + // Alternate content doesn't trigger a pluginError, and nsPluginCrashedEvent + // is only handled by ::PluginCrashed + FirePluginError(mFallbackType); + } +} + void nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner, bool aDelayedStop, @@ -2155,7 +2311,7 @@ nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner, { // DoStopPlugin can process events and there may be pending InDocCheckEvent // events which can drop in underneath us and destroy the instance we are - // about to destroy unless we prevent that with the mIsStopping flag. + // about to destroy unless we prevent that with the mPluginStopping flag. // (aForcedReentry is only true from the callback of an earlier delayed stop) if (mIsStopping && !aForcedReentry) { return; @@ -2174,22 +2330,35 @@ nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner, aInstanceOwner->HidePluginWindow(); #endif - nsCOMPtr pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID); - NS_ASSERTION(pluginHost, "Without a pluginHost, how can we have an instance to destroy?"); - static_cast(pluginHost.get())->StopPluginInstance(inst); + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); + NS_ASSERTION(pluginHost, "No plugin host?"); + pluginHost->StopPluginInstance(inst); } - + aInstanceOwner->Destroy(); - mIsStopping = false; } NS_IMETHODIMP nsObjectLoadingContent::StopPluginInstance() { + // Prevents any pending plugin starts from running + mPendingInstantiateEvent = nullptr; + if (!mInstanceOwner) { return NS_OK; } + if (mChannel) { + // The plugin has already used data from this channel, we'll need to + // re-open it to handle instantiating again, even if we don't invalidate + // our loaded state. + /// XXX(johns): Except currently, we don't, just leaving re-opening channels + /// to plugins... + LOG(("OBJLC [%p]: StopPluginInstance - Closing used channel", this)); + CloseChannel(); + } + DisconnectFrame(); bool delayedStop = false; @@ -2202,7 +2371,7 @@ nsObjectLoadingContent::StopPluginInstance() if (NS_SUCCEEDED(inst->GetMIMEType(&mime)) && mime) { if (strcmp(mime, "audio/x-pn-realaudio-plugin") == 0) { delayedStop = true; - } + } } } #endif @@ -2217,39 +2386,40 @@ nsObjectLoadingContent::StopPluginInstance() void nsObjectLoadingContent::NotifyContentObjectWrapper() { - nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + nsCOMPtr thisContent = + do_QueryInterface(static_cast(this)); nsCOMPtr doc = thisContent->GetDocument(); if (!doc) return; - + nsIScriptGlobalObject *sgo = doc->GetScopeObject(); if (!sgo) return; - + nsIScriptContext *scx = sgo->GetContext(); if (!scx) return; - + JSContext *cx = scx->GetNativeContext(); - + nsCOMPtr wrapper; nsContentUtils::XPConnect()-> GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent, NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); - + if (!wrapper) { // Nothing to do here if there's no wrapper for mContent. The proto // chain will be fixed appropriately when the wrapper is created. return; } - + JSObject *obj = nullptr; nsresult rv = wrapper->GetJSObject(&obj); if (NS_FAILED(rv)) return; - + nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj); } @@ -2259,13 +2429,90 @@ nsObjectLoadingContent::PlayPlugin() if (!nsContentUtils::IsCallerChrome()) return NS_OK; - mCTPPlayable = true; - return LoadObject(mURI, true, mContentType, true); + mActivated = true; + return LoadObject(true, true); } NS_IMETHODIMP -nsObjectLoadingContent::GetActivated(bool* aActivated) +nsObjectLoadingContent::GetActivated(bool *aActivated) { - *aActivated = mActivated; + FallbackType reason; + *aActivated = ShouldPlay(reason); return NS_OK; } + +bool +nsObjectLoadingContent::ShouldPlay(FallbackType &aReason) +{ + // mActivated is true if we've been activated via PlayPlugin() (e.g. user has + // clicked through). Otherwise, only play if click-to-play is off or if page + // is whitelisted + + nsRefPtr pluginHost = + already_AddRefed(nsPluginHost::GetInst()); + + bool isCTP = pluginHost->IsPluginClickToPlayForType(mContentType.get()); + + if (!isCTP || mActivated) { + return true; + } + + aReason = eFallbackClickToPlay; + + // If plugin type is click-to-play and we have not been explicitly clicked. + // check if permissions lets this page bypass - (e.g. user selected 'Always + // play plugins on this page') + nsresult rv = NS_ERROR_UNEXPECTED; + + nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); + MOZ_ASSERT(thisContent); + nsIDocument* ownerDoc = thisContent->OwnerDoc(); + + nsCOMPtr window = ownerDoc->GetWindow(); + if (!window) { + return false; + } + nsCOMPtr topWindow; + rv = window->GetTop(getter_AddRefs(topWindow)); + NS_ENSURE_SUCCESS(rv, false); + nsCOMPtr topDocument; + rv = topWindow->GetDocument(getter_AddRefs(topDocument)); + NS_ENSURE_SUCCESS(rv, false); + nsCOMPtr topDoc = do_QueryInterface(topDocument); + nsIURI* topUri = topDoc->GetDocumentURI(); + + nsCOMPtr permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, false); + + bool allowPerm = false; + // For now we always say that the system principal uses click-to-play since + // that maintains current behavior and we have tests that expect this. + // What we really should do is disable plugins entirely in pages that use + // the system principal, i.e. in chrome pages. That way the click-to-play + // code here wouldn't matter at all. Bug 775301 is tracking this. + if (!nsContentUtils::IsSystemPrincipal(topDoc->NodePrincipal())) { + PRUint32 permission; + rv = permissionManager->TestPermissionFromPrincipal(topDoc->NodePrincipal(), + "plugins", + &permission); + NS_ENSURE_SUCCESS(rv, false); + allowPerm = permission == nsIPermissionManager::ALLOW_ACTION; + } + + PRUint32 state; + rv = pluginHost->GetBlocklistStateForType(mContentType.get(), &state); + NS_ENSURE_SUCCESS(rv, false); + + // Always c2p vulnerable plugins, regardless of permissions + if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) { + aReason = eFallbackVulnerableUpdatable; + return false; + } + if (state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) { + aReason = eFallbackVulnerableNoUpdate; + return false; + } + + return allowPerm; +} + diff --git a/content/base/src/nsObjectLoadingContent.h b/content/base/src/nsObjectLoadingContent.h index cf7e3f62cab9..bedefdd7ddee 100644 --- a/content/base/src/nsObjectLoadingContent.h +++ b/content/base/src/nsObjectLoadingContent.h @@ -31,36 +31,6 @@ class AutoFallback; class AutoSetInstantiatingToFalse; class nsObjectFrame; -enum PluginSupportState { - ePluginUnsupported, // The plugin is not supported (e.g. not installed) - ePluginDisabled, // The plugin has been explicitly disabled by the user - ePluginBlocklisted, // The plugin is blocklisted and disabled - ePluginOutdated, // The plugin is considered outdated, but not disabled - ePluginOtherState, // Something else (e.g. uninitialized or not a plugin) - ePluginCrashed, - ePluginClickToPlay, // The plugin is disabled until the user clicks on it - ePluginVulnerableUpdatable, // The plugin is vulnerable (update available) - ePluginVulnerableNoUpdate // The plugin is vulnerable (no update available) -}; - -/** - * INVARIANTS OF THIS CLASS - * - mChannel is non-null between asyncOpen and onStopRequest (NOTE: Only needs - * to be valid until onStopRequest is called on mFinalListener, not - * necessarily until the channel calls onStopRequest on us) - * - mChannel corresponds to the channel that gets passed to the - * nsIRequestObserver/nsIStreamListener methods - * - mChannel can be cancelled and ODA calls will stop - * - mFinalListener is non-null (only) after onStartRequest has been called on - * it and before onStopRequest has been called on it - * (i.e. calling onStopRequest doesn't violate the nsIRequestObserver - * contract) - * - mFrameLoader is null while this node is not in a document (XXX this - * invariant only exists due to nsFrameLoader suckage and needs to go away) - * - mInstantiating is true while in LoadObject (it may be true in other - * cases as well). Only the function that set mInstantiating should trigger - * frame construction or notifications like ContentStatesChanged or flushes. - */ class nsObjectLoadingContent : public nsImageLoadingContent , public nsIStreamListener , public nsIFrameLoaderOwner @@ -68,9 +38,9 @@ class nsObjectLoadingContent : public nsImageLoadingContent , public nsIInterfaceRequestor , public nsIChannelEventSink { - friend class AutoNotifier; - friend class AutoFallback; friend class AutoSetInstantiatingToFalse; + friend class AutoSetLoadingToFalse; + friend class InDocCheckEvent; friend class nsStopPluginRunnable; friend class nsAsyncInstantiateEvent; @@ -78,11 +48,33 @@ class nsObjectLoadingContent : public nsImageLoadingContent // This enum's values must be the same as the constants on // nsIObjectLoadingContent enum ObjectType { - eType_Loading = TYPE_LOADING, ///< Type not yet known - eType_Image = TYPE_IMAGE, ///< This content is an image - eType_Plugin = TYPE_PLUGIN, ///< This content is a plugin - eType_Document = TYPE_DOCUMENT, ///< This is a document type (e.g. HTML) - eType_Null = TYPE_NULL ///< Type can't be handled + // Loading, type not yet known. We may be waiting for a channel to open. + eType_Loading = TYPE_LOADING, + // Content is a *non-svg* image + eType_Image = TYPE_IMAGE, + // Content is a plugin + eType_Plugin = TYPE_PLUGIN, + // Content is a subdocument, possibly SVG + eType_Document = TYPE_DOCUMENT, + // No content loaded (fallback). May be showing alternate content or + // a custom error handler - *including* click-to-play dialogs + eType_Null = TYPE_NULL + }; + enum FallbackType { + eFallbackUnsupported, // The content type is not supported (e.g. plugin + // not installed) + eFallbackAlternate, // Showing alternate content + eFallbackDisabled, // The plugin exists, but is disabled + eFallbackBlocklisted, // The plugin is blocklisted and disabled + eFallbackOutdated, // The plugin is considered outdated, but not + // disabled + eFallbackCrashed, // The plugin has crashed + eFallbackSuppressed, // Suppressed by security policy + eFallbackUserDisabled, // Blocked by content policy + eFallbackClickToPlay, // The plugin is disabled until the user clicks on + // it + eFallbackVulnerableUpdatable, // The plugin is vulnerable (update avail) + eFallbackVulnerableNoUpdate // The plugin is vulnerable (no update avail) }; nsObjectLoadingContent(); @@ -102,110 +94,106 @@ class nsObjectLoadingContent : public nsImageLoadingContent using nsImageLoadingContent::OnStopRequest; #endif - ObjectType Type() { return mType; } - /** - * Object state. This is a bitmask consisting of a subset of - * NS_EVENT_STATE_BROKEN, NS_EVENT_STATE_USERDISABLED and - * NS_EVENT_STATE_SUPPRESSED representing the current state of the object. + * Object state. This is a bitmask of NS_EVENT_STATEs epresenting the + * current state of the object. */ nsEventStates ObjectState() const; + ObjectType Type() { return mType; } + void SetIsNetworkCreated(bool aNetworkCreated) { mNetworkCreated = aNetworkCreated; } - // Can flush layout. - nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI); + /** + * Immediately instantiate a plugin instance. This is a no-op if + * mType != eType_Plugin or a plugin is already running. + */ + nsresult InstantiatePluginInstance(); + /** + * Notify this class the document state has changed + * Called by nsDocument so we may suspend plugins in inactive documents) + */ void NotifyOwnerDocumentActivityChanged(); + /** + * Used by pluginHost to know if we're loading with a channel, so it + * will not open its own. + */ bool SrcStreamLoading() { return mSrcStreamLoading; }; protected: /** - * Load the object from the given URI. - * @param aURI The URI to load. - * @param aNotify If true, nsIDocumentObserver state change notifications - * will be sent as needed. - * @param aTypeHint MIME Type hint. Overridden by the server unless this - * class has the eOverrideServerType capability. - * @param aForceLoad If true, the object will be refetched even if the URI - * is the same as the currently-loaded object. - * @note Prefer the nsIURI-taking version of this function if a URI object - * is already available. - * @see the URI-taking version of this function for a detailed description - * of how a plugin will be found. - */ - nsresult LoadObject(const nsAString& aURI, - bool aNotify, - const nsCString& aTypeHint = EmptyCString(), - bool aForceLoad = false); - /** - * Loads the object from the given URI. + * Begins loading the object when called * - * The URI and type can both be null; if the URI is null a plugin will be - * instantiated in the hope that there is a with a useful URI - * somewhere around. Other attributes of |this| QI'd to nsIContent will be - * inspected. This function attempts hard to find a suitable plugin. + * Attributes of |this| QI'd to nsIContent will be inspected, depending on + * the node type. This function currently assumes it is a , + * , or tag. * - * The instantiated plugin depends on three values: - * - The passed-in URI - * - The passed-in type hint + * The instantiated plugin depends on: + * - The URI (, ) + * - The type 'hint' (type attribute) + * - The mime type returned by opening the URI + * - Enabled plugins claiming the ultimate mime type + * - The capabilities returned by GetCapabilities * - The classid attribute, if eSupportClassID is among the capabilities - * and such an attribute is present.. * - * Supported class ID attributes override any other value. - * - * If no class ID is present and aForceType is true, the handler given by - * aTypeHint will be instantiated for this content. - * If the URI is null or not supported, and a type hint is given, the plugin - * corresponding to that type is instantiated. + * If eAllowPluginSkipChannel is true, we may skip opening the URI if our + * type hint points to a valid plugin, deferring that responsibility to the + * plugin. + * Similarly, if no URI is provided, but a type hint for a valid plugin is + * present, that plugin will be instantiated * * Otherwise a request to that URI is made and the type sent by the server - * is used to find a suitable handler. + * is used to find a suitable handler, EXCEPT when: + * - The type hint refers to a *supported* plugin, in which case that + * plugin will be instantiated regardless of the server provided type + * - The server returns a binary-stream type, and our type hint refers to + * a valid non-document type, we will use the type hint * - * @param aForceLoad If true, the object will be refetched even if the URI - * is the same as the currently-loaded object. + * @param aNotify If we should send notifications. If false, content + * loading may be deferred while appropriate frames are + * created + * @param aForceLoad If we should reload this content (and re-attempt the + * channel open) even if our parameters did not change */ - nsresult LoadObject(nsIURI* aURI, - bool aNotify, - const nsCString& aTypeHint = EmptyCString(), + nsresult LoadObject(bool aNotify, bool aForceLoad = false); enum Capabilities { - eSupportImages = PR_BIT(0), // Images are supported (imgILoader) - eSupportPlugins = PR_BIT(1), // Plugins are supported (nsIPluginHost) - eSupportDocuments = PR_BIT(2), // Documents are supported - // (nsIDocumentLoaderFactory) - // This flag always includes SVG - eSupportSVG = PR_BIT(3), // SVG is supported (image/svg+xml) - eSupportClassID = PR_BIT(4), // The classid attribute is supported - eOverrideServerType = PR_BIT(5) // The server-sent MIME type is ignored - // (ignored if no type is specified) + eSupportImages = PR_BIT(0), // Images are supported (imgILoader) + eSupportPlugins = PR_BIT(1), // Plugins are supported (nsIPluginHost) + eSupportDocuments = PR_BIT(2), // Documents are supported + // (nsIDocumentLoaderFactory) + // This flag always includes SVG + eSupportSVG = PR_BIT(3), // SVG is supported (image/svg+xml) + eSupportClassID = PR_BIT(4), // The classid attribute is supported + + // Allows us to load a plugin if it matches a MIME type or file extension + // registered to a plugin without opening its specified URI first. Can + // result in launching plugins for URIs that return differing content + // types. Plugins without URIs may instantiate regardless. + // XXX(johns) this is our legacy behavior on tags, whereas object + // will always open a channel and check its MIME if a URI is present. + eAllowPluginSkipChannel = PR_BIT(5) }; /** * Returns the list of capabilities this content node supports. This is a * bitmask consisting of flags from the Capabilities enum. * - * The default implementation supports all types but no classids. + * The default implementation supports all types but not + * eSupportClassID or eAllowPluginSkipChannel */ virtual PRUint32 GetCapabilities() const; /** - * Fall back to rendering the alternative content. + * Destroys all loaded documents/plugins and releases references */ - void Fallback(bool aNotify); - - /** - * Subclasses must call this function when they are removed from the - * document. - * - * XXX This is a temporary workaround for docshell suckyness - */ - void RemovedFromDocument(); + void DestroyContent(); static void Traverse(nsObjectLoadingContent *tmp, nsCycleCollectionTraversalCallback &cb); @@ -222,30 +210,127 @@ class nsObjectLoadingContent : public nsImageLoadingContent bool aNullParent = true); private: + // Object parameter changes returned by UpdateObjectParameters + enum ParameterUpdateFlags { + eParamNoChange = 0, + // Parameters that potentially affect the channel changed + // - mOriginalURI, mOriginalContentType + eParamChannelChanged = PR_BIT(0), + // Parameters that affect displayed content changed + // - mURI, mContentType, mType, mBaseURI + eParamStateChanged = PR_BIT(1) + }; + + /** + * Loads fallback content with the specified FallbackType + * + * @param aType FallbackType value for type of fallback we're loading + * @param aNotify Send notifications and events. If false, caller is + * responsible for doing so + */ + void LoadFallback(FallbackType aType, bool aNotify); + + /** + * Internal version of LoadObject that should only be used by this class + * aLoadingChannel is passed by the LoadObject call from OnStartRequest, + * primarily for sanity-preservation + */ + nsresult LoadObject(bool aNotify, + bool aForceLoad, + nsIRequest *aLoadingChannel); + + /** + * Introspects the object and sets the following member variables: + * - mOriginalContentType : This is the type attribute on the element + * - mOriginalURI : The src or data attribute on the element + * - mURI : The final URI, considering mChannel if + * mChannelLoaded is set + * - mContentType : The final content type, considering mChannel if + * mChannelLoaded is set + * - mBaseURI : The object's base URI, which may be set by the + * object (codebase attribute) + * - mType : The type the object is determined to be based + * on the above + * + * NOTE The class assumes that mType is the currently loaded type at various + * points, so the caller of this function must take the appropriate + * actions to ensure this + * + * NOTE This function does not perform security checks, only determining the + * requested type and parameters of the object. + * + * @return Returns a bitmask of ParameterUpdateFlags values + */ + ParameterUpdateFlags UpdateObjectParameters(); void NotifyContentObjectWrapper(); /** - * Check whether the given request represents a successful load. + * Opens the channel pointed to by mURI into mChannel. + * + * @param aPolicyType The value to be passed to channelPolicy->SetLoadType */ - static bool IsSuccessfulRequest(nsIRequest* aRequest); + nsresult OpenChannel(PRInt32 aPolicyType); /** - * Check whether the URI can be handled internally. + * Closes and releases references to mChannel and, if opened, mFinalListener */ - static bool CanHandleURI(nsIURI* aURI); + nsresult CloseChannel(); /** - * Checks whether the given type is a supported document type. + * If this object is allowed to play plugin content, or if it would display + * click-to-play instead. + * NOTE that this does not actually check if the object is a loadable plugin + */ + bool ShouldPlay(FallbackType &aReason); + + /** + * Checks if a URI passes security checks and content policy, relative to + * the current document's principal + * + * @param aURI The URI to consider + * @param aContentPolicy [in/out] A pointer to the initial content + * policy, that will be updated to contain the + * final determined policy + * @param aContentPolicyType The 'contentType' parameter passed to + * NS_CheckContentLoadPolicy + * + * @return true if this URI is acceptable for loading + */ + bool CheckURILoad(nsIURI *aURI, + PRInt16 *aContentPolicy, + PRInt32 aContentPolicyType); + + /** + * Checks if the current mURI and mBaseURI pass content policy and security + * checks for loading + * + * @param aContentPolicy [in/out] A pointer to the initial content + * policy, that will be updated to contain the + * final determined policy if a URL is rejected + * @param aContentPolicyType The 'contentType' parameter passed to + * NS_CheckContentLoadPolicy + * + * @return true if the URIs are acceptable for loading + */ + bool CheckObjectURIs(PRInt16 *aContentPolicy, PRInt32 aContentPolicyType); + + /** + * Checks whether the given type is a supported document type + * + * NOTE Does not take content policy or capabilities into account */ bool IsSupportedDocument(const nsCString& aType); /** - * Unload the currently loaded content. This removes all state related to - * the displayed content and sets the type to eType_Null. - * Note: This does not send any notifications. + * Unloads all content and resets the object to a completely unloaded state + * + * NOTE Calls StopPluginInstance() and may spin the event loop + * + * @param aResetState Reset the object type to 'loading' and destroy channel + * as well */ - void UnloadContent(); + void UnloadObject(bool aResetState = true); /** * Notifies document observes about a new type/state of this object. @@ -261,141 +346,112 @@ class nsObjectLoadingContent : public nsImageLoadingContent bool aSync, bool aNotify); /** - * Fires the "Plugin not found" event. This function doesn't do any checks - * whether it should be fired, the caller should do that. + * Fires the nsPluginErrorEvent. This function doesn't do any checks + * whether it should be fired, or whether the given state translates to a + * meaningful event */ - static void FirePluginError(nsIContent* thisContent, PluginSupportState state); + void FirePluginError(FallbackType aFallbackType); + /** + * Returns a ObjectType value corresponding to the type of content we would + * support the given MIME type as, taking capabilities and plugin state + * into account + * + * NOTE this does not consider whether the content would be suppressed by + * click-to-play or other content policy checks + */ ObjectType GetTypeOfContent(const nsCString& aMIMEType); /** * For a classid, returns the MIME type that can be used to instantiate * a plugin for this ID. * + * @param aClassID The class ID in question + * @param aType [out] The corresponding type, if the call is successful * @return NS_ERROR_NOT_AVAILABLE Unsupported class ID. */ nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType); - /** - * Gets the base URI to be used for this object. This differs from - * nsIContent::GetBaseURI in that it takes codebase attributes into - * account. - */ - void GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI); - - /** * Gets the frame that's associated with this content node. * Does not flush. */ nsObjectFrame* GetExistingFrame(); - /** - * Handle being blocked by a content policy. aStatus is the nsresult - * return value of the Should* call, while aRetval is what it returned in - * its out parameter. - */ - void HandleBeingBlockedByContentPolicy(nsresult aStatus, - PRInt16 aRetval); - - /** - * Get the plugin support state for the given content node and MIME type. - * This is used for purposes of determining whether to fire PluginNotFound - * events etc. aContentType is the MIME type we ended up with. - * - * This should only be called if the type of this content is eType_Null. - */ - PluginSupportState GetPluginSupportState(nsIContent* aContent, const nsCString& aContentType); - - /** - * If the plugin for aContentType is disabled, return ePluginDisabled. - * Otherwise (including if there is no plugin for aContentType at all), - * return ePluginUnsupported. - * - * This should only be called if the type of this content is eType_Null. - */ - PluginSupportState GetPluginDisabledState(const nsCString& aContentType); - - /** - * When there is no usable plugin available this will send UI events and - * update the AutoFallback object appropriate to the reason for there being - * no plugin available. - */ - void UpdateFallbackState(nsIContent* aContent, AutoFallback& fallback, const nsCString& aTypeHint); - - nsresult IsPluginEnabledForType(const nsCString& aMIMEType); - bool IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType); - - /** - * The final listener to ship the data to (imagelib, uriloader, etc) - */ + // The final listener for mChannel (uriloader, pluginstreamlistener, etc.) nsCOMPtr mFinalListener; - /** - * Frame loader, for content documents we load. - */ + // Frame loader, for content documents we load. nsRefPtr mFrameLoader; - /** - * A pending nsAsyncInstantiateEvent (may be null). This is a weak ref. - */ + // A pending nsAsyncInstantiateEvent (may be null). This is a weak ref. nsIRunnable *mPendingInstantiateEvent; - /** - * The content type of the resource we were last asked to load. - */ + // The content type of our current load target, updated by + // UpdateObjectParameters(). Takes the channel's type into account once + // opened. + // + // May change if a channel is opened, does not imply a loaded state nsCString mContentType; - /** - * The channel that's currently being loaded. This is a weak reference. - * Non-null between asyncOpen and onStopRequest. - */ - nsIChannel* mChannel; + // The content type 'hint' provided by the element's type attribute. May + // or may not be used as a final type + nsCString mOriginalContentType; - // The data we were last asked to load + // The channel that's currently being loaded. If set, but mChannelLoaded is + // false, has not yet reached OnStartRequest + nsCOMPtr mChannel; + + // The URI of the current content. + // May change as we open channels and encounter redirects - does not imply + // a loaded type nsCOMPtr mURI; - /** - * Type of the currently-loaded content. - */ - ObjectType mType : 16; + // The original URI obtained from inspecting the element (codebase, and + // src/data). May differ from mURI due to redirects + nsCOMPtr mOriginalURI; - /** - * Whether we are about to call instantiate on our frame. If we aren't, - * SetFrame needs to asynchronously call Instantiate. - */ + // The baseURI used for constructing mURI, and used by some plugins (java) + // as a root for other resource requests. + nsCOMPtr mBaseURI; + + + + // Type of the currently-loaded content. + ObjectType mType : 8; + // The type of fallback content we're showing (see ObjectState()) + FallbackType mFallbackType : 8; + + // If true, the current load has finished opening a channel. Does not imply + // mChannel -- mChannelLoaded && !mChannel may occur for a load that failed + bool mChannelLoaded : 1; + + // Whether we are about to call instantiate on our frame. If we aren't, + // SetFrame needs to asynchronously call Instantiate. bool mInstantiating : 1; - // Blocking status from content policy - bool mUserDisabled : 1; - bool mSuppressed : 1; // True when the object is created for an element which the parser has // created using NS_FROM_PARSER_NETWORK flag. If the element is modified, // it may lose the flag. bool mNetworkCreated : 1; - // Used to keep track of if a plugin is blocked by click-to-play. - // True indicates the plugin is not click-to-play or it has been clicked by - // the user. - // False indicates the plugin is click-to-play and has not yet been clicked. - bool mCTPPlayable : 1; - - // Used to keep track of whether or not a plugin has been played. - // This is used for click-to-play plugins. + // Used to keep track of whether or not a plugin has been explicitly + // activated by PlayPlugin(). (see ShouldPlay()) bool mActivated : 1; // Protects DoStopPlugin from reentry (bug 724781). bool mIsStopping : 1; + // Protects LoadObject from re-entry + bool mIsLoading : 1; + // Used to track when we might try to instantiate a plugin instance based on - // a src data stream being delivered to this object. When this is true we don't - // want plugin instance instantiation code to attempt to load src data again or - // we'll deliver duplicate streams. Should be cleared when we are not loading - // src data. + // a src data stream being delivered to this object. When this is true we + // don't want plugin instance instantiation code to attempt to load src data + // again or we'll deliver duplicate streams. Should be cleared when we are + // not loading src data. bool mSrcStreamLoading; - // A specific state that caused us to fallback - PluginSupportState mFallbackReason; nsWeakFrame mPrintFrame; diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index bf787d09c0aa..8db6b159e414 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -3699,7 +3699,6 @@ nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress) if (aFinalProgress) { mUploadTotal = mUploadTransferred; mUploadProgressMax = mUploadProgress; - mUploadLengthComputable = true; } if (mUpload && !mUploadComplete) { DispatchProgressEvent(mUpload, NS_LITERAL_STRING(PROGRESS_STR), @@ -3710,7 +3709,6 @@ nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress) } else { if (aFinalProgress) { mLoadTotal = mLoadTransferred; - mLoadLengthComputable = true; } mInLoadProgressEvent = true; DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR), diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index db53ac8d8ed4..19083ab0ce24 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -3570,7 +3570,7 @@ JS::Value nsCanvasRenderingContext2DAzure::GetMozDash(JSContext* cx, ErrorResult& error) { JS::Value mozDash; - DashArrayToJSVal(CurrentState().dash, cx, &mozDash); + error = DashArrayToJSVal(CurrentState().dash, cx, &mozDash); return mozDash; } diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 844ef12df31e..f542a6b67dd7 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -10,6 +10,7 @@ #include "IPC/IPCMessageUtils.h" #include "nsCOMPtr.h" +#include "nsDOMError.h" #include "nsDOMEvent.h" #include "nsEventStateManager.h" #include "nsIFrame.h" diff --git a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp index f0c9f5739703..437eff635e51 100644 --- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp +++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp @@ -4,6 +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 "nsDOMError.h" #include "nsDOMNotifyAudioAvailableEvent.h" #include "nsDOMClassInfoID.h" // DOMCI_DATA, NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO #include "nsContentUtils.h" // NS_DROP_JS_OBJECTS diff --git a/content/html/content/src/nsDOMStringMap.cpp b/content/html/content/src/nsDOMStringMap.cpp index 356c8b188b0d..833f46ea75cc 100644 --- a/content/html/content/src/nsDOMStringMap.cpp +++ b/content/html/content/src/nsDOMStringMap.cpp @@ -4,6 +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 "nsDOMError.h" #include "nsDOMStringMap.h" #include "nsDOMClassInfoID.h" diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index 199ec6d89fa3..9a5ac2e87d9c 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -3,6 +3,7 @@ /* 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 "nsDOMError.h" #include "nsIDOMHTMLAudioElement.h" #include "nsHTMLAudioElement.h" #include "nsGenericHTMLElement.h" diff --git a/content/html/content/src/nsHTMLMenuElement.cpp b/content/html/content/src/nsHTMLMenuElement.cpp index b3e67a010852..f202345e9d7c 100644 --- a/content/html/content/src/nsHTMLMenuElement.cpp +++ b/content/html/content/src/nsHTMLMenuElement.cpp @@ -11,6 +11,7 @@ #include "nsEventDispatcher.h" #include "nsHTMLMenuItemElement.h" #include "nsContentUtils.h" +#include "nsDOMError.h" enum MenuType { diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index 25ac0f0c091f..930f38b6c620 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -268,7 +268,6 @@ void nsHTMLObjectElement::UnbindFromTree(bool aDeep, bool aNullParent) { - RemovedFromDocument(); nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent); } @@ -280,10 +279,12 @@ nsHTMLObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName, nsIAtom *aPrefix, const nsAString &aValue, bool aNotify) { - // If we plan to call LoadObject, we want to do it first so that the - // object load kicks off _before_ the reflow triggered by the SetAttr. But if - // aNotify is false, we are coming from the parser or some such place; we'll - // get bound after all the attributes have been set, so we'll do the + nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName, aPrefix, + aValue, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + + // if aNotify is false, we are coming from the parser or some such place; + // we'll get bound after all the attributes have been set, so we'll do the // object load from BindToTree/DoneAddingChildren. // Skip the LoadObject call in that case. // We also don't want to start loading the object when we're not yet in @@ -291,24 +292,27 @@ nsHTMLObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName, // attributes before inserting the node into the document. if (aNotify && IsInDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) { - nsAutoString type; - GetAttr(kNameSpaceID_None, nsGkAtoms::type, type); - LoadObject(aValue, aNotify, NS_ConvertUTF16toUTF8(type), true); + return LoadObject(aNotify, true); } - return nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); + return NS_OK; } nsresult nsHTMLObjectElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, bool aNotify) { - if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { - Fallback(aNotify); + nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, + aAttribute, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + + // See comment in SetAttr + if (aNotify && IsInDoc() && mIsDoneAddingChildren && + aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { + return LoadObject(aNotify, true); } - return nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); + return NS_OK; } bool @@ -513,20 +517,7 @@ nsHTMLObjectElement::GetAttributeMappingFunction() const void nsHTMLObjectElement::StartObjectLoad(bool aNotify) { - nsAutoString type; - GetAttr(kNameSpaceID_None, nsGkAtoms::type, type); - NS_ConvertUTF16toUTF8 ctype(type); - - nsAutoString uri; - if (GetAttr(kNameSpaceID_None, nsGkAtoms::data, uri)) { - LoadObject(uri, aNotify, ctype); - } - else { - // Be sure to call the nsIURI version if we have no attribute - // That handles the case where no URI is specified. An empty string would - // get interpreted as the page itself, instead of absence of URI. - LoadObject(nullptr, aNotify, ctype); - } + LoadObject(aNotify); SetIsNetworkCreated(false); } @@ -545,7 +536,7 @@ nsHTMLObjectElement::GetCapabilities() const void nsHTMLObjectElement::DestroyContent() { - RemovedFromDocument(); + nsObjectLoadingContent::DestroyContent(); nsGenericHTMLFormElement::DestroyContent(); } diff --git a/content/html/content/src/nsHTMLSharedObjectElement.cpp b/content/html/content/src/nsHTMLSharedObjectElement.cpp index b68df7e18594..7f1147f8ad1c 100644 --- a/content/html/content/src/nsHTMLSharedObjectElement.cpp +++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp @@ -298,22 +298,22 @@ void nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep, bool aNullParent) { - RemovedFromDocument(); nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); } - nsresult nsHTMLSharedObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName, nsIAtom *aPrefix, const nsAString &aValue, bool aNotify) { - // If we plan to call LoadObject, we want to do it first so that the - // object load kicks off _before_ the reflow triggered by the SetAttr. But if - // aNotify is false, we are coming from the parser or some such place; we'll - // get bound after all the attributes have been set, so we'll do the + nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, + aValue, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + + // if aNotify is false, we are coming from the parser or some such place; + // we'll get bound after all the attributes have been set, so we'll do the // object load from BindToTree/DoneAddingChildren. // Skip the LoadObject call in that case. // We also don't want to start loading the object when we're not yet in @@ -321,13 +321,10 @@ nsHTMLSharedObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName, // attributes before inserting the node into the document. if (aNotify && IsInDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == URIAttrName()) { - nsCAutoString type; - GetTypeAttrValue(type); - LoadObject(aValue, aNotify, type, true); + return LoadObject(aNotify, true); } - return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, - aNotify); + return NS_OK; } bool @@ -468,19 +465,7 @@ nsHTMLSharedObjectElement::GetAttributeMappingFunction() const void nsHTMLSharedObjectElement::StartObjectLoad(bool aNotify) { - nsCAutoString type; - GetTypeAttrValue(type); - - nsAutoString uri; - if (!GetAttr(kNameSpaceID_None, URIAttrName(), uri)) { - // Be sure to call the nsIURI version if we have no attribute - // That handles the case where no URI is specified. An empty string would - // get interpreted as the page itself, instead of absence of URI. - LoadObject(nullptr, aNotify, type); - } - else { - LoadObject(uri, aNotify, type); - } + LoadObject(aNotify); SetIsNetworkCreated(false); } @@ -493,7 +478,7 @@ nsHTMLSharedObjectElement::IntrinsicState() const PRUint32 nsHTMLSharedObjectElement::GetCapabilities() const { - PRUint32 capabilities = eSupportPlugins | eOverrideServerType; + PRUint32 capabilities = eSupportPlugins | eAllowPluginSkipChannel; if (mNodeInfo->Equals(nsGkAtoms::embed)) { capabilities |= eSupportSVG | eSupportImages; } @@ -504,7 +489,7 @@ nsHTMLSharedObjectElement::GetCapabilities() const void nsHTMLSharedObjectElement::DestroyContent() { - RemovedFromDocument(); + nsObjectLoadingContent::DestroyContent(); nsGenericHTMLElement::DestroyContent(); } diff --git a/content/html/document/src/PluginDocument.cpp b/content/html/document/src/PluginDocument.cpp index 668da4b8f87f..e61cd10548b8 100644 --- a/content/html/document/src/PluginDocument.cpp +++ b/content/html/document/src/PluginDocument.cpp @@ -120,8 +120,7 @@ PluginStreamListener::SetupPlugin() return NS_ERROR_UNEXPECTED; } nsObjectLoadingContent* olcc = static_cast(olc.get()); - nsresult rv = olcc->InstantiatePluginInstance(mPluginDoc->GetType().get(), - mDocument->nsIDocument::GetDocumentURI()); + nsresult rv = olcc->InstantiatePluginInstance(); if (NS_FAILED(rv)) { return rv; } diff --git a/content/smil/nsSMILTimedElement.h b/content/smil/nsSMILTimedElement.h index ce83168fede0..8ea415653514 100644 --- a/content/smil/nsSMILTimedElement.h +++ b/content/smil/nsSMILTimedElement.h @@ -6,6 +6,7 @@ #ifndef NS_SMILTIMEDELEMENT_H_ #define NS_SMILTIMEDELEMENT_H_ +#include "nsISMILAnimationElement.h" #include "nsSMILInterval.h" #include "nsSMILInstanceTime.h" #include "nsSMILMilestone.h" @@ -18,7 +19,6 @@ #include "nsAutoPtr.h" #include "nsAttrValue.h" -class nsISMILAnimationElement; class nsSMILAnimationFunction; class nsSMILTimeContainer; class nsSMILTimeValue; diff --git a/content/svg/content/src/DOMSVGTransformList.cpp b/content/svg/content/src/DOMSVGTransformList.cpp index f783e08434ae..793f9e6c80e6 100644 --- a/content/svg/content/src/DOMSVGTransformList.cpp +++ b/content/svg/content/src/DOMSVGTransformList.cpp @@ -10,6 +10,7 @@ #include "nsSVGElement.h" #include "nsContentUtils.h" #include "dombindings.h" +#include "nsDOMError.h" // local helper functions namespace { diff --git a/content/svg/content/src/SVGAnimatedTransformList.cpp b/content/svg/content/src/SVGAnimatedTransformList.cpp index 140cc2a7bf0d..52a28a2cfbdf 100644 --- a/content/svg/content/src/SVGAnimatedTransformList.cpp +++ b/content/svg/content/src/SVGAnimatedTransformList.cpp @@ -6,6 +6,7 @@ #include "SVGAnimatedTransformList.h" #include "DOMSVGAnimatedTransformList.h" +#include "nsISMILAnimationElement.h" #include "nsSMILValue.h" #include "SVGTransform.h" #include "SVGTransformListSMILType.h" diff --git a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp index add97d6e5daa..756ab7d66911 100644 --- a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp +++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SVGMotionSMILAnimationFunction.h" +#include "nsISMILAnimationElement.h" #include "nsSMILParserUtils.h" #include "nsSVGAngle.h" #include "SVGMotionSMILType.h" diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index 04954fea672f..3e33d8d73991 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -4,6 +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 "nsDOMError.h" #include "SVGTransform.h" #include "nsContentUtils.h" #include "nsTextFormatter.h" diff --git a/content/svg/content/src/nsSVGBoolean.cpp b/content/svg/content/src/nsSVGBoolean.cpp index 54eaf7f0277a..05fed56dff92 100644 --- a/content/svg/content/src/nsSVGBoolean.cpp +++ b/content/svg/content/src/nsSVGBoolean.cpp @@ -3,6 +3,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 "nsDOMError.h" #include "nsSVGBoolean.h" #include "nsSMILValue.h" #include "SMILBoolType.h" diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 1ca5e3a807b0..c7563cab170f 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -56,6 +56,7 @@ #include "nsSMILMappedAttribute.h" #include "SVGMotionSMILAttr.h" #include "nsAttrValueOrString.h" +#include "nsSMILAnimationController.h" using namespace mozilla; diff --git a/content/svg/content/src/nsSVGEnum.cpp b/content/svg/content/src/nsSVGEnum.cpp index 198f4e6ae406..3642aea55db3 100644 --- a/content/svg/content/src/nsSVGEnum.cpp +++ b/content/svg/content/src/nsSVGEnum.cpp @@ -3,6 +3,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 "nsDOMError.h" #include "nsSVGEnum.h" #include "nsIAtom.h" #include "nsSVGElement.h" diff --git a/content/svg/content/src/nsSVGInteger.cpp b/content/svg/content/src/nsSVGInteger.cpp index ba35f5a31c41..e01550b7efb0 100644 --- a/content/svg/content/src/nsSVGInteger.cpp +++ b/content/svg/content/src/nsSVGInteger.cpp @@ -3,6 +3,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 "nsDOMError.h" #include "nsSVGInteger.h" #include "nsSMILValue.h" #include "SMILIntegerType.h" diff --git a/content/svg/content/src/nsSVGNumber2.cpp b/content/svg/content/src/nsSVGNumber2.cpp index 3bb34feeb6cd..691cbd373b69 100644 --- a/content/svg/content/src/nsSVGNumber2.cpp +++ b/content/svg/content/src/nsSVGNumber2.cpp @@ -3,6 +3,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 "nsDOMError.h" #include "nsSVGNumber2.h" #include "nsSVGUtils.h" #include "nsTextFormatter.h" diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 537ffbc012d1..c93079a88ae2 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -781,7 +781,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, bool aNotify) controlElement->GetSelectedCount(&length); for (PRInt32 i = 0; i < length; i++) { nsCOMPtr node; - controlElement->GetSelectedItem(i, getter_AddRefs(node)); + controlElement->MultiGetSelectedItem(i, getter_AddRefs(node)); // we need to QI here to do an XPCOM-correct pointercompare nsCOMPtr selElem = do_QueryInterface(node); if (selElem == oldKidElem && diff --git a/content/xul/templates/src/nsXULTreeBuilder.cpp b/content/xul/templates/src/nsXULTreeBuilder.cpp index 88f4d1182048..cd5724c51a4d 100644 --- a/content/xul/templates/src/nsXULTreeBuilder.cpp +++ b/content/xul/templates/src/nsXULTreeBuilder.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nscore.h" +#include "nsDOMError.h" #include "nsIContent.h" #include "nsINodeInfo.h" #include "nsIDOMElement.h" diff --git a/docshell/base/LoadContext.cpp b/docshell/base/LoadContext.cpp new file mode 100644 index 000000000000..c8512ce2da26 --- /dev/null +++ b/docshell/base/LoadContext.cpp @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/LoadContext.h" +#include "nsIScriptSecurityManager.h" +#include "nsServiceManagerUtils.h" +#include "nsContentUtils.h" + +namespace mozilla { + +NS_IMPL_ISUPPORTS1(LoadContext, nsILoadContext); + +//----------------------------------------------------------------------------- +// LoadContext::nsILoadContext +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +LoadContext::GetAssociatedWindow(nsIDOMWindow**) +{ + MOZ_ASSERT(mIsNotNull); + + // can't support this in the parent process + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +LoadContext::GetTopWindow(nsIDOMWindow**) +{ + MOZ_ASSERT(mIsNotNull); + + // can't support this in the parent process + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +LoadContext::IsAppOfType(PRUint32, bool*) +{ + MOZ_ASSERT(mIsNotNull); + + // don't expect we need this in parent (Thunderbird/SeaMonkey specific?) + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +LoadContext::GetIsContent(bool* aIsContent) +{ + MOZ_ASSERT(mIsNotNull); + + NS_ENSURE_ARG_POINTER(aIsContent); + + *aIsContent = mIsContent; + return NS_OK; +} + +NS_IMETHODIMP +LoadContext::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) +{ + MOZ_ASSERT(mIsNotNull); + + NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); + + *aUsePrivateBrowsing = mUsePrivateBrowsing; + return NS_OK; +} + +NS_IMETHODIMP +LoadContext::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) +{ + MOZ_ASSERT(mIsNotNull); + + // We shouldn't need this on parent... + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +LoadContext::GetIsInBrowserElement(bool* aIsInBrowserElement) +{ + MOZ_ASSERT(mIsNotNull); + + NS_ENSURE_ARG_POINTER(aIsInBrowserElement); + + *aIsInBrowserElement = mIsInBrowserElement; + return NS_OK; +} + +NS_IMETHODIMP +LoadContext::GetAppId(PRUint32* aAppId) +{ + MOZ_ASSERT(mIsNotNull); + + NS_ENSURE_ARG_POINTER(aAppId); + + *aAppId = mAppId; + return NS_OK; +} + +NS_IMETHODIMP +LoadContext::GetExtendedOrigin(nsIURI* aUri, nsACString& aResult) +{ + MOZ_ASSERT(mIsNotNull); + + nsIScriptSecurityManager* ssmgr = nsContentUtils::GetSecurityManager(); + + return ssmgr->GetExtendedOrigin(aUri, mAppId, mIsInBrowserElement, aResult); +} + +} // namespace mozilla diff --git a/docshell/base/LoadContext.h b/docshell/base/LoadContext.h new file mode 100644 index 000000000000..7cf38e6c9e12 --- /dev/null +++ b/docshell/base/LoadContext.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef LoadContext_h +#define LoadContext_h + +#include "SerializedLoadContext.h" + +namespace mozilla { + +/** + * Class that provides nsILoadContext info in Parent process. Typically copied + * from Child via SerializedLoadContext. + * + * Note: this is not the "normal" or "original" nsILoadContext. That is + * typically provided by nsDocShell. This is only used when the original + * docshell is in a different process and we need to copy certain values from + * it. + */ + +class LoadContext : public nsILoadContext +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSILOADCONTEXT + + LoadContext(const IPC::SerializedLoadContext& toCopy) + : mIsNotNull(toCopy.mIsNotNull) + , mIsContent(toCopy.mIsContent) + , mUsePrivateBrowsing(toCopy.mUsePrivateBrowsing) + , mIsInBrowserElement(toCopy.mIsInBrowserElement) + , mAppId(toCopy.mAppId) + {} + +private: + bool mIsNotNull; + bool mIsContent; + bool mUsePrivateBrowsing; + bool mIsInBrowserElement; + PRUint32 mAppId; +}; + +} // namespace mozilla + +#endif // LoadContext_h + diff --git a/docshell/base/Makefile.in b/docshell/base/Makefile.in index ab683ab95fc6..f4b1c23f81c4 100644 --- a/docshell/base/Makefile.in +++ b/docshell/base/Makefile.in @@ -56,12 +56,14 @@ EXPORTS = \ nsDocShellLoadTypes.h \ nsILinkHandler.h \ nsIWebShellServices.h \ + SerializedLoadContext.h \ $(NULL) EXPORTS_NAMESPACES = mozilla EXPORTS_mozilla = \ IHistory.h \ + LoadContext.h \ $(NULL) CPPSRCS = \ @@ -75,6 +77,8 @@ CPPSRCS = \ nsWebNavigationInfo.cpp \ nsAboutRedirector.cpp \ nsDownloadHistory.cpp \ + SerializedLoadContext.cpp \ + LoadContext.cpp \ $(NULL) # we don't want the shared lib, but we want to force the creation of a diff --git a/docshell/base/SerializedLoadContext.cpp b/docshell/base/SerializedLoadContext.cpp new file mode 100644 index 000000000000..ec52b5619355 --- /dev/null +++ b/docshell/base/SerializedLoadContext.cpp @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SerializedLoadContext.h" +#include "nsNetUtil.h" +#include "nsIChannel.h" +#include "nsIWebSocketChannel.h" + +namespace IPC { + +SerializedLoadContext::SerializedLoadContext(nsILoadContext* aLoadContext) +{ + Init(aLoadContext); +} + +SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel) +{ + nsCOMPtr loadContext; + NS_QueryNotificationCallbacks(aChannel, loadContext); + Init(loadContext); +} + +SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel) +{ + nsCOMPtr loadContext; + NS_QueryNotificationCallbacks(aChannel, loadContext); + Init(loadContext); +} + +void +SerializedLoadContext::Init(nsILoadContext* aLoadContext) +{ + if (aLoadContext) { + mIsNotNull = true; + aLoadContext->GetIsContent(&mIsContent); + aLoadContext->GetUsePrivateBrowsing(&mUsePrivateBrowsing); + aLoadContext->GetAppId(&mAppId); + aLoadContext->GetIsInBrowserElement(&mIsInBrowserElement); + } else { + mIsNotNull = false; + // none of below values really matter when mIsNotNull == false: + // we won't be GetInterfaced to nsILoadContext + mIsContent = true; + mUsePrivateBrowsing = false; + mAppId = 0; + mIsInBrowserElement = false; + } +} + +} // namespace IPC + diff --git a/docshell/base/SerializedLoadContext.h b/docshell/base/SerializedLoadContext.h new file mode 100644 index 000000000000..bd0d299a8485 --- /dev/null +++ b/docshell/base/SerializedLoadContext.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef SerializedLoadContext_h +#define SerializedLoadContext_h + +#include "base/basictypes.h" +#include "IPC/IPCMessageUtils.h" +#include "nsIIPCSerializable.h" +#include "nsILoadContext.h" + +/* + * This file contains the IPC::SerializedLoadContext class, which is used to + * copy data across IPDL from Child process contexts so it is available in the + * Parent. + */ + +class nsIChannel; +class nsIWebSocketChannel; + +namespace IPC { + +class SerializedLoadContext +{ +public: + SerializedLoadContext() + { + Init(nsnull); + } + + SerializedLoadContext(nsILoadContext* aLoadContext); + SerializedLoadContext(nsIChannel* aChannel); + SerializedLoadContext(nsIWebSocketChannel* aChannel); + + void Init(nsILoadContext* aLoadContext); + + bool IsNotNull() const + { + return mIsNotNull; + } + + // used to indicate if child-side LoadContext * was null. + bool mIsNotNull; + bool mIsContent; + bool mUsePrivateBrowsing; + bool mIsInBrowserElement; + PRUint32 mAppId; +}; + +// Function to serialize over IPDL +template<> +struct ParamTraits +{ + typedef SerializedLoadContext paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mIsNotNull); + WriteParam(aMsg, aParam.mIsContent); + WriteParam(aMsg, aParam.mUsePrivateBrowsing); + WriteParam(aMsg, aParam.mAppId); + WriteParam(aMsg, aParam.mIsInBrowserElement); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &aResult->mIsNotNull) || + !ReadParam(aMsg, aIter, &aResult->mIsContent) || + !ReadParam(aMsg, aIter, &aResult->mUsePrivateBrowsing) || + !ReadParam(aMsg, aIter, &aResult->mAppId) || + !ReadParam(aMsg, aIter, &aResult->mIsInBrowserElement)) { + return false; + } + + return true; + } +}; + +} // namespace IPC + +#endif // SerializedLoadContext_h + diff --git a/dom/apps/src/Webapps.js b/dom/apps/src/Webapps.js index 5a067bc5318e..775ef148941f 100644 --- a/dom/apps/src/Webapps.js +++ b/dom/apps/src/Webapps.js @@ -135,11 +135,13 @@ WebappsRegistry.prototype = { Services.DOMRequest.fireError(request, "INVALID_MANIFEST"); } else { let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : []; + let categories = (aParams && aParams.categories && Array.isArray(aParams.categories)) ? aParams.categories : []; cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin, origin: this._getOrigin(aURL), manifestURL: aURL, manifest: manifest, - receipts: receipts }, + receipts: receipts, + categories: categories }, from: installURL, oid: this._id, requestID: requestID }); @@ -191,8 +193,11 @@ WebappsRegistry.prototype = { let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : []; + let categories = (aParams && aParams.categories && + Array.isArray(aParams.categories)) ? aParams.categories : []; cpmm.sendAsyncMessage("Webapps:InstallPackage", { url: aPackageURL, receipts: receipts, + categories: categories, requestID: requestID, oid: this._id, from: this._window.location.href, diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 26e6f7f8e1ce..4ac7ff9ab3ba 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -502,7 +502,7 @@ let DOMApplicationRegistry = { } // Build a data structure to call the webapps confirmation dialog : // - load the manifest from the zip - // - set data.app.(origin, install_origin, manifestURL, manifest, receipts) + // - set data.app.(origin, install_origin, manifestURL, manifest, receipts, categories) // - call notifyObservers(this, "webapps-ask-install", JSON.stringify(msg)); let msg = { from: aData.from, @@ -513,7 +513,8 @@ let DOMApplicationRegistry = { installOrigin: aData.installOrigin, origin: "app://" + id, manifestURL: manifestURL, - receipts: aData.receipts + receipts: aData.receipts, + categories: aData.categories } } let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"] diff --git a/dom/base/Makefile.in b/dom/base/Makefile.in index 3f1443bb3a0d..97be3d0b020f 100644 --- a/dom/base/Makefile.in +++ b/dom/base/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 8fdf133287fb..a8435f7ee0c7 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -652,6 +652,19 @@ Navigator::AddIdleObserver(nsIIdleObserver* aIdleObserver) nsCOMPtr win = do_QueryReferent(mWindow); NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED); + + nsCOMPtr doc = win->GetExtantDoc(); + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); + + nsIPrincipal* principal = doc->NodePrincipal(); + if (!nsContentUtils::IsSystemPrincipal(principal)) { + PRUint16 appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; + principal->GetAppStatus(&appStatus); + if (appStatus != nsIPrincipal::APP_STATUS_CERTIFIED) { + return NS_ERROR_DOM_SECURITY_ERR; + } + } + if (NS_FAILED(win->RegisterIdleObserver(aIdleObserver))) { NS_WARNING("Failed to add idle observer."); } diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d6a2710ca90a..c2b05fdb4d40 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -5756,11 +5756,21 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner, JSObject* thisObject = &thisValue.toObject(); // wrap parameters in the target compartment + // we also pass in the calling window as the first argument + ++argc; nsAutoArrayPtr args(new JS::Value[argc]); JS::AutoArrayRooter rooter(cx, 0, args); - for (size_t i = 0; i < argc; ++i) { - args[i] = argv[i]; + nsCOMPtr holder; + nsCOMPtr currentWin(do_GetInterface(currentInner)); + rv = WrapNative(cx, obj, currentWin, &NS_GET_IID(nsIDOMWindow), + true, &args[0], getter_AddRefs(holder)); + if (!JS_WrapValue(cx, &args[0])) + return NS_ERROR_FAILURE; + rooter.changeLength(1); + + for (size_t i = 1; i < argc; ++i) { + args[i] = argv[i - 1]; if (!JS_WrapValue(cx, &args[i])) return NS_ERROR_FAILURE; rooter.changeLength(i + 1); diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h index 83f59e782b57..810e847799d5 100644 --- a/dom/base/nsDOMNavigationTiming.h +++ b/dom/base/nsDOMNavigationTiming.h @@ -128,7 +128,6 @@ private: DOMTimeMilliSec mBeforeUnloadStart; DOMTimeMilliSec mUnloadStart; DOMTimeMilliSec mUnloadEnd; - DOMTimeMilliSec mNavigationEnd; DOMTimeMilliSec mLoadEventStart; DOMTimeMilliSec mLoadEventEnd; diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 964ecb877ec9..9dbe8fa14e5d 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -2272,7 +2272,7 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument, startContent != aDocument->GetRootElement()) { // Yes, indeed we were at the end of the last node nsFrameIterator frameTraversal(presContext, startFrame, - eLeaf, FrameIteratorFlags::FLAG_FOLLOW_OUT_OF_FLOW); + eLeaf, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW); nsIFrame *newCaretFrame = nullptr; nsCOMPtr newCaretContent = startContent; @@ -2698,7 +2698,7 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell, } nsFrameIterator frameTraversal(presContext, startFrame, - ePreOrder, FrameIteratorFlags::FLAG_FOLLOW_OUT_OF_FLOW); + ePreOrder, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW); if (iterStartContent == aRootContent) { if (!aForward) { diff --git a/dom/base/nsHistory.cpp b/dom/base/nsHistory.cpp index fd6fb4c53e0d..49f56fe4b295 100644 --- a/dom/base/nsHistory.cpp +++ b/dom/base/nsHistory.cpp @@ -23,6 +23,7 @@ #include "nsXPIDLString.h" #include "nsReadableUtils.h" #include "nsDOMClassInfoID.h" +#include "nsDOMError.h" #include "nsContentUtils.h" #include "nsISHistoryInternal.h" #include "mozilla/Preferences.h" diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 69be047e5bde..d1d374bf1b9d 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -4,6 +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 "nsDOMError.h" #include "nsJSEnvironment.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptObjectPrincipal.h" diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index fa6f29ba06f1..606f3c5fa471 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -6,6 +6,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 MODULE = dom LIBRARY_NAME = dombindings_s diff --git a/dom/file/FileRequest.cpp b/dom/file/FileRequest.cpp index 6fc8d4e66291..8b626fc51f8b 100644 --- a/dom/file/FileRequest.cpp +++ b/dom/file/FileRequest.cpp @@ -10,6 +10,7 @@ #include "nsContentUtils.h" #include "nsEventDispatcher.h" +#include "nsDOMError.h" #include "nsDOMProgressEvent.h" #include "nsDOMClassInfoID.h" #include "FileHelper.h" @@ -149,14 +150,20 @@ FileRequest::FireProgressEvent(PRUint64 aLoaded, PRUint64 aTotal) nsRefPtr event = new nsDOMProgressEvent(nullptr, nullptr); nsresult rv = event->InitProgressEvent(NS_LITERAL_STRING("progress"), false, false, false, aLoaded, aTotal); - NS_ENSURE_SUCCESS(rv,); + if (NS_FAILED(rv)) { + return; + } rv = event->SetTrusted(true); - NS_ENSURE_SUCCESS(rv,); + if (NS_FAILED(rv)) { + return; + } bool dummy; rv = DispatchEvent(static_cast(event), &dummy); - NS_ENSURE_SUCCESS(rv,); + if (NS_FAILED(rv)) { + return; + } } void diff --git a/dom/file/FileService.cpp b/dom/file/FileService.cpp index 1d3045650dec..c85c4ccdd1df 100644 --- a/dom/file/FileService.cpp +++ b/dom/file/FileService.cpp @@ -389,7 +389,9 @@ FileService::LockedFileQueue::OnFileHelperComplete(FileHelper* aFileHelper) mCurrentHelper = nullptr; nsresult rv = ProcessQueue(); - NS_ENSURE_SUCCESS(rv,); + if (NS_FAILED(rv)) { + return; + } } } diff --git a/dom/file/Makefile.in b/dom/file/Makefile.in index 26753586f96f..e7ba5d2c7857 100644 --- a/dom/file/Makefile.in +++ b/dom/file/Makefile.in @@ -6,6 +6,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in index 9ec06780bc42..4c5b0deb0f8e 100644 --- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in +++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in @@ -1,11 +1,11 @@ # THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT -DEPTH = ../../../../../../../.. +DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -relativesrcdir = dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger +relativesrcdir = @relativesrcdir@ DIRS = \ $(NULL) diff --git a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in b/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in index 093338ca9c44..23b2c20327dc 100644 --- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in +++ b/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in @@ -1,11 +1,11 @@ # THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT -DEPTH = ../../../../../../.. +DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -relativesrcdir = dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger +relativesrcdir = @relativesrcdir@ DIRS = \ $(NULL) diff --git a/dom/imptests/writeMakefile.py b/dom/imptests/writeMakefile.py index 76787042c488..68db418f4208 100644 --- a/dom/imptests/writeMakefile.py +++ b/dom/imptests/writeMakefile.py @@ -6,12 +6,12 @@ import string makefileTemplate = """# THIS FILE IS AUTOGENERATED BY ${caller} - DO NOT EDIT -DEPTH = ${depth} +DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -relativesrcdir = ${relativesrcdir} +relativesrcdir = @relativesrcdir@ DIRS = \\ ${dirs} @@ -34,8 +34,6 @@ def makefileString(entries): def substMakefile(caller, path, subdirs, files): result = string.Template(makefileTemplate).substitute({ "caller": caller, - "depth": "..%s" % ("/.." * path.count("/"), ), - "relativesrcdir": path, "dirs": makefileString(subdirs) }) diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index bfddc5b6ecfc..69d52ae5f36a 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1393,8 +1393,7 @@ IDBObjectStore::ConvertActorsToBlobs( NS_ASSERTION(aFiles.IsEmpty(), "Should be empty!"); if (!aActors.IsEmpty()) { - ContentChild* contentChild = ContentChild::GetSingleton(); - NS_ASSERTION(contentChild, "This should never be null!"); + NS_ASSERTION(ContentChild::GetSingleton(), "This should never be null!"); PRUint32 length = aActors.Length(); aFiles.SetCapacity(length); diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp index 47b87fe28090..cd80e85a822d 100644 --- a/dom/indexedDB/Key.cpp +++ b/dom/indexedDB/Key.cpp @@ -105,7 +105,8 @@ Key::EncodeJSValInternal(JSContext* aCx, const jsval aVal, { NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR); - PR_STATIC_ASSERT(eMaxType * MaxArrayCollapse < 256); + MOZ_STATIC_ASSERT(eMaxType * MaxArrayCollapse < 256, + "Unable to encode jsvals."); if (JSVAL_IS_STRING(aVal)) { nsDependentJSString str; diff --git a/dom/indexedDB/Makefile.in b/dom/indexedDB/Makefile.in index db32fab22777..dfa74b6af636 100644 --- a/dom/indexedDB/Makefile.in +++ b/dom/indexedDB/Makefile.in @@ -6,6 +6,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 3d190bca9d10..0ee9b0482c35 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -24,7 +24,8 @@ namespace { // If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major // schema version. -PR_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1); +MOZ_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1, + "Need to update the major schema version."); // Major schema version. Bump for almost everything. const PRUint32 kMajorSchemaVersion = 12; @@ -36,8 +37,10 @@ const PRUint32 kMinorSchemaVersion = 0; // The schema version we store in the SQLite database is a (signed) 32-bit // integer. The major version is left-shifted 4 bits so the max value is // 0xFFFFFFF. The minor version occupies the lower 4 bits and its max is 0xF. -PR_STATIC_ASSERT(kMajorSchemaVersion <= 0xFFFFFFF); -PR_STATIC_ASSERT(kMajorSchemaVersion <= 0xF); +MOZ_STATIC_ASSERT(kMajorSchemaVersion <= 0xFFFFFFF, + "Major version needs to fit in 28 bits."); +MOZ_STATIC_ASSERT(kMinorSchemaVersion <= 0xF, + "Minor version needs to fit in 4 bits."); inline PRInt32 @@ -1800,7 +1803,8 @@ OpenDatabaseHelper::CreateDatabaseConnection( } else { // This logic needs to change next time we change the schema! - PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((12 << 4) + 0)); + MOZ_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((12 << 4) + 0), + "Need upgrade code from schema version increase."); while (schemaVersion != kSQLiteSchemaVersion) { if (schemaVersion == 4) { diff --git a/dom/indexedDB/ipc/IndexedDBChild.h b/dom/indexedDB/ipc/IndexedDBChild.h index e53d934acb99..9a39f78fa15d 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.h +++ b/dom/indexedDB/ipc/IndexedDBChild.h @@ -314,7 +314,7 @@ class IndexedDBObjectStoreRequestChild : public IndexedDBRequestChildBase typedef ipc::ObjectStoreRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; public: IndexedDBObjectStoreRequestChild(AsyncConnectionHelper* aHelper, @@ -337,7 +337,7 @@ class IndexedDBIndexRequestChild : public IndexedDBRequestChildBase typedef ipc::IndexRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; public: IndexedDBIndexRequestChild(AsyncConnectionHelper* aHelper, IDBIndex* aIndex, @@ -359,7 +359,7 @@ class IndexedDBCursorRequestChild : public IndexedDBRequestChildBase typedef ipc::CursorRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; public: IndexedDBCursorRequestChild(AsyncConnectionHelper* aHelper, diff --git a/dom/indexedDB/ipc/IndexedDBParent.cpp b/dom/indexedDB/ipc/IndexedDBParent.cpp index ab76891868ee..a56f802f4915 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.cpp +++ b/dom/indexedDB/ipc/IndexedDBParent.cpp @@ -1197,9 +1197,7 @@ IndexedDBObjectStoreRequestParent::ConvertBlobActors( if (!aActors.IsEmpty()) { // Walk the chain to get to ContentParent. - ContentParent* contentParent = - mObjectStore->Transaction()->Database()->GetContentParent(); - MOZ_ASSERT(contentParent); + MOZ_ASSERT(mObjectStore->Transaction()->Database()->GetContentParent()); uint32_t length = aActors.Length(); aBlobs.SetCapacity(length); diff --git a/dom/indexedDB/ipc/IndexedDBParent.h b/dom/indexedDB/ipc/IndexedDBParent.h index 2d13013449a2..725b10686d7e 100644 --- a/dom/indexedDB/ipc/IndexedDBParent.h +++ b/dom/indexedDB/ipc/IndexedDBParent.h @@ -494,7 +494,7 @@ class IndexedDBObjectStoreRequestParent : public IndexedDBRequestParentBase typedef ipc::ObjectStoreRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; typedef ipc::AddParams AddParams; typedef ipc::PutParams PutParams; @@ -550,7 +550,7 @@ class IndexedDBIndexRequestParent : public IndexedDBRequestParentBase typedef ipc::IndexRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; typedef ipc::GetKeyParams GetKeyParams; typedef ipc::GetAllKeysParams GetAllKeysParams; @@ -596,7 +596,7 @@ class IndexedDBCursorRequestParent : public IndexedDBRequestParentBase typedef ipc::CursorRequestParams ParamsUnionType; typedef ParamsUnionType::Type RequestType; - RequestType mRequestType; + DebugOnly mRequestType; typedef ipc::ContinueParams ContinueParams; diff --git a/dom/indexedDB/ipc/Makefile.in b/dom/indexedDB/ipc/Makefile.in index 46ad31fd8d8d..060ac467dd55 100644 --- a/dom/indexedDB/ipc/Makefile.in +++ b/dom/indexedDB/ipc/Makefile.in @@ -7,6 +7,7 @@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ relativesrcdir = @relativesrcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk @@ -31,8 +32,7 @@ LOCAL_INCLUDES += \ DEFINES += -D_IMPL_NS_LAYOUT -# Bug 770046 - Cannot fail. -# MOCHITEST_FILES = test_ipc.html +MOCHITEST_FILES = test_ipc.html # Need to enable these tests sometime soon. #XPCSHELL_TESTS = unit @@ -49,4 +49,4 @@ copy-xpcshell-tests: $(call install_cmd,$(wildcard $(topsrcdir)/dom/indexedDB/test/unit/test_*.js) \ $(testxpcobjdir)/$(relativesrcdir)/$(XPCSHELL_TESTS)) -libs-xpcshell-tests: copy-xpcshell-tests \ No newline at end of file +libs-xpcshell-tests: copy-xpcshell-tests diff --git a/dom/interfaces/apps/nsIDOMApplicationRegistry.idl b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl index 58e7c3fcb8ca..efa5f4320bdc 100644 --- a/dom/interfaces/apps/nsIDOMApplicationRegistry.idl +++ b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl @@ -74,7 +74,10 @@ interface mozIDOMApplicationRegistry : nsISupports * * @param manifestUrl : the URL of the webapps manifest. * @param parameters : A structure with optional information. - * { receipts: ... } will be used to specify the payment receipts for this installation. + * { + * receipts: ... Will be used to specify the payment receipts for this installation. + * categories: ... Will be used to specify the categories of the webapp. + * } * @returns : A DOMRequest object, returning the app object in |result| if install succeeds. */ nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters); @@ -100,7 +103,10 @@ interface mozIDOMApplicationRegistry : nsISupports * * @param packageUrl : the URL of the webapps manifest. * @param parameters : A structure with optional information. - * { receipts: ... } will be used to specify the payment receipts for this installation. + * { + * receipts: ... Will be used to specify the payment receipts for this installation. + * categories: ... Will be used to specify the categories of the webapp. + * } * @returns : A DOMRequest object, returning the app object in |result| if install succeeds. */ nsIDOMDOMRequest installPackage(in DOMString packageUrl, [optional] in jsval parameters); diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 1401a9be9f49..3eab8a8e0d04 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -752,7 +752,7 @@ interface nsIDOMWindowUtils : nsISupports { /** * Synthesize a query content event. * - * @param aType On of the following const values. And see also each comment + * @param aType One of the following const values. And see also each comment * for the other parameters and the result. */ nsIQueryContentEventResult sendQueryContentEvent(in unsigned long aType, @@ -761,29 +761,6 @@ interface nsIDOMWindowUtils : nsISupports { in long aX, in long aY); - - /** - * Called when the remote child frame has changed its fullscreen state, - * when entering fullscreen, and when the origin which is fullscreen changes. - * aFrameElement is the iframe element which contains the child-process - * fullscreen document, and aNewOrigin is the origin of the new fullscreen - * document. - */ - void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement, - in AString aNewOrigin); - - /** - * Called when the remote frame has popped all fullscreen elements off its - * stack, so that the operation can complete on the parent side. - */ - void remoteFrameFullscreenReverted(); - - /** - * Called when the child frame has fully exit fullscreen, so that the parent - * process can also fully exit. - */ - void exitFullscreen(); - // NOTE: following values are same as NS_QUERY_* in nsGUIEvent.h /** @@ -872,6 +849,28 @@ interface nsIDOMWindowUtils : nsISupports { */ const unsigned long QUERY_CHARACTER_AT_POINT = 3208; + /** + * Called when the remote child frame has changed its fullscreen state, + * when entering fullscreen, and when the origin which is fullscreen changes. + * aFrameElement is the iframe element which contains the child-process + * fullscreen document, and aNewOrigin is the origin of the new fullscreen + * document. + */ + void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement, + in AString aNewOrigin); + + /** + * Called when the remote frame has popped all fullscreen elements off its + * stack, so that the operation can complete on the parent side. + */ + void remoteFrameFullscreenReverted(); + + /** + * Called when the child frame has fully exit fullscreen, so that the parent + * process can also fully exit. + */ + void exitFullscreen(); + /** * Synthesize a selection set event to the window. * diff --git a/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl b/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl index 83101b27f7df..cf917483bc94 100644 --- a/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl +++ b/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl @@ -29,5 +29,6 @@ interface nsIDOMXULMultiSelectControlElement : nsIDOMXULSelectControlElement // XXX - temporary, pending implementation of scriptable, // mutable nsIDOMNodeList for selectedItems readonly attribute long selectedCount; + [binaryname(MultiGetSelectedItem)] nsIDOMXULSelectControlItemElement getSelectedItem(in long index); }; diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 9a388f813dc4..879fe81112ef 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -189,9 +189,6 @@ private: InfallibleTArray > mAlertObservers; nsRefPtr mConsoleListener; -#ifdef ANDROID - gfxIntSize mScreenSize; -#endif /** * An ID unique to the process containing our corresponding @@ -204,6 +201,10 @@ private: AppInfo mAppInfo; +#ifdef ANDROID + gfxIntSize mScreenSize; +#endif + static ContentChild* sSingleton; DISALLOW_EVIL_CONSTRUCTORS(ContentChild); diff --git a/dom/ipc/CrashReporterParent.cpp b/dom/ipc/CrashReporterParent.cpp index 1800225dfd1d..0f89cc0d9c8c 100644 --- a/dom/ipc/CrashReporterParent.cpp +++ b/dom/ipc/CrashReporterParent.cpp @@ -127,7 +127,7 @@ CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes) mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type); char startTime[32]; - sprintf(startTime, "%lld", static_cast(mStartTime)); + sprintf(startTime, "%lld", static_cast(mStartTime)); mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime)); if (!mAppNotes.IsEmpty()) diff --git a/dom/ipc/Makefile.in b/dom/ipc/Makefile.in index d1a96fe9e730..8f14f729356f 100644 --- a/dom/ipc/Makefile.in +++ b/dom/ipc/Makefile.in @@ -14,6 +14,7 @@ LIBRARY_NAME = domipc_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +FAIL_ON_WARNINGS := 1 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT)) TEST_DIRS += tests diff --git a/dom/plugins/base/Makefile.in b/dom/plugins/base/Makefile.in index 79c2377504c4..688614f4bd59 100644 --- a/dom/plugins/base/Makefile.in +++ b/dom/plugins/base/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp index f9f96ba56726..c86566d6eef0 100644 --- a/dom/plugins/base/PluginPRLibrary.cpp +++ b/dom/plugins/base/PluginPRLibrary.cpp @@ -23,6 +23,7 @@ static int gNotOptimized; #include "AndroidBridge.h" #include "android_npapi.h" #include +#undef ALOG #define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoJavaEnv", ## args) #endif diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index d9c257de482b..193d5fef3a32 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -101,6 +101,7 @@ using mozilla::plugins::PluginModuleParent; #include "android_npapi.h" #include "ANPBase.h" #include "AndroidBridge.h" +#undef LOG #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) #endif diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 0dac36f3d9ae..4aa49ad31e5a 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -170,7 +170,6 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance() mDrawingModel(kDefaultDrawingModel), #ifdef MOZ_WIDGET_ANDROID mANPDrawingModel(0), - mOnScreen(true), mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary), mWakeLocked(false), mFullScreen(false), @@ -191,6 +190,9 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance() #else mUsePluginLayersPref(false) #endif +#ifdef MOZ_WIDGET_ANDROID + , mOnScreen(true) +#endif { mNPP.pdata = NULL; mNPP.ndata = this; diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index 14a12164a605..80fb6e38c7f8 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -2201,7 +2201,7 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, // Avoid adding different versions of the same plugin if they are running // in-process, otherwise we risk undefined behaviour. if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) { - if (nsPluginTag *duplicate = HaveSamePlugin(pluginTag)) { + if (HaveSamePlugin(pluginTag)) { continue; } } diff --git a/dom/plugins/base/nsPluginStreamListenerPeer.cpp b/dom/plugins/base/nsPluginStreamListenerPeer.cpp index 29f6a66cbcf6..d85fe5284163 100644 --- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp +++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp @@ -601,7 +601,7 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, // if we have a mime type now. if (!mPluginInstance && mContent && !aContentType.IsEmpty()) { nsObjectLoadingContent *olc = static_cast(mContent.get()); - rv = olc->InstantiatePluginInstance(aContentType.get(), aURL.get()); + rv = olc->InstantiatePluginInstance(); if (NS_SUCCEEDED(rv)) { rv = olc->GetPluginInstance(getter_AddRefs(mPluginInstance)); if (NS_FAILED(rv)) { diff --git a/dom/plugins/ipc/Makefile.in b/dom/plugins/ipc/Makefile.in index 07c5cc4db069..e890fa8a4a03 100644 --- a/dom/plugins/ipc/Makefile.in +++ b/dom/plugins/ipc/Makefile.in @@ -6,6 +6,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index d30cf9895305..ea960fd5cf0b 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -1218,9 +1218,9 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) (void) mPluginIface->setwindow(&mData, &mWindow); #elif defined(ANDROID) -# warning Need Android impl + // TODO: Need Android impl #elif defined(MOZ_WIDGET_QT) -# warning Need QT-nonX impl + // TODO: Need QT-nonX impl #else # error Implement me for your OS #endif @@ -3520,8 +3520,8 @@ PluginInstanceChild::ShowPluginFrame() } #endif - NS_ASSERTION(mWindow.width == (mWindow.clipRect.right - mWindow.clipRect.left) && - mWindow.height == (mWindow.clipRect.bottom - mWindow.clipRect.top), + NS_ASSERTION(mWindow.width == uint32_t(mWindow.clipRect.right - mWindow.clipRect.left) && + mWindow.height == uint32_t(mWindow.clipRect.bottom - mWindow.clipRect.top), "Clip rect should be same size as window when using layers"); // Clear accRect here to be able to pass diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 7a4b488ab62d..ec6b46494e10 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -12,12 +12,12 @@ #include "StreamNotifyParent.h" #include "npfunctions.h" #include "nsAutoPtr.h" -#include "mozilla/unused.h" #include "gfxASurface.h" #include "gfxContext.h" #include "gfxPlatform.h" #include "gfxSharedImageSurface.h" #include "nsNPAPIPluginInstance.h" +#include "mozilla/StandardInteger.h" // for intptr_t #ifdef MOZ_X11 #include "gfxXlibSurface.h" #endif @@ -222,10 +222,10 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle* #elif defined(XP_MACOSX) intptr_t id; #elif defined(ANDROID) -#warning Need Android impl + // TODO: Need Android impl int id; #elif defined(MOZ_WIDGET_QT) -# warning Need Qt non X impl + // TODO: Need Qt non X impl int id; #else #warning Implement me @@ -331,9 +331,11 @@ bool PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow( const bool& windowed, NPError* result) { - NPBool isWindowed = windowed; + // Yes, we are passing a boolean as a void*. We have to cast to intptr_t + // first to avoid gcc warnings about casting to a pointer from a + // non-pointer-sized integer. *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool, - (void*)isWindowed); + (void*)(intptr_t)windowed); return true; } @@ -341,9 +343,8 @@ bool PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent( const bool& transparent, NPError* result) { - NPBool isTransparent = transparent; *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool, - (void*)isTransparent); + (void*)(intptr_t)transparent); return true; } @@ -352,7 +353,7 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor( const bool& useDOMForCursor, NPError* result) { *result = mNPNIface->setvalue(mNPP, NPPVpluginUsesDOMForCursorBool, - (void*)(NPBool)useDOMForCursor); + (void*)(intptr_t)useDOMForCursor); return true; } @@ -1020,7 +1021,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) if (mDrawingModel == NPDrawingModelCoreAnimation || mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) { mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height); - } else if (mShWidth * mShHeight != window.width * window.height) { + } else if (uint32_t(mShWidth * mShHeight) != window.width * window.height) { if (mShWidth != 0 && mShHeight != 0) { DeallocShmem(mShSurface); mShWidth = 0; diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index 859274468663..bcdc30a074ab 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -27,7 +27,9 @@ #ifdef MOZ_X11 class gfxXlibSurface; #endif +#include "mozilla/unused.h" #include "nsGUIEvent.h" +#include "mozilla/unused.h" namespace mozilla { namespace plugins { @@ -280,7 +282,7 @@ public: nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled); #endif - void DidComposite() { SendNPP_DidComposite(); } + void DidComposite() { unused << SendNPP_DidComposite(); } private: // Create an appropriate platform surface for a background of size diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index e66a3e897448..994602bd9cc2 100644 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -313,9 +313,8 @@ PluginModuleParent::CrashReporter() { return static_cast(ManagedPCrashReporterParent()[0]); } -#endif -#ifdef MOZ_CRASHREPORTER +#ifdef MOZ_CRASHREPORTER_INJECTOR static void RemoveMinidump(nsIFile* minidump) { @@ -329,6 +328,7 @@ RemoveMinidump(nsIFile* minidump) extraFile->Remove(true); } } +#endif // MOZ_CRASHREPORTER_INJECTOR void PluginModuleParent::ProcessFirstMinidump() diff --git a/dom/power/PowerManager.cpp b/dom/power/PowerManager.cpp index 581d8e08dc3a..a817a4bfe90f 100644 --- a/dom/power/PowerManager.cpp +++ b/dom/power/PowerManager.cpp @@ -13,6 +13,7 @@ #include "nsIPrincipal.h" #include "nsPIDOMWindow.h" #include "nsServiceManagerUtils.h" +#include "nsDOMError.h" DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager) diff --git a/dom/src/events/Makefile.in b/dom/src/events/Makefile.in index 156a6d91feb6..cfa091c20d73 100644 --- a/dom/src/events/Makefile.in +++ b/dom/src/events/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/src/json/Makefile.in b/dom/src/json/Makefile.in index 7052e1027bcc..0a058c9f5b39 100644 --- a/dom/src/json/Makefile.in +++ b/dom/src/json/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/src/jsurl/Makefile.in b/dom/src/jsurl/Makefile.in index 7fceca2a39dd..decdf33c9f18 100644 --- a/dom/src/jsurl/Makefile.in +++ b/dom/src/jsurl/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/src/jsurl/nsJSProtocolHandler.h b/dom/src/jsurl/nsJSProtocolHandler.h index cd8dfa0d72de..a6793476db30 100644 --- a/dom/src/jsurl/nsJSProtocolHandler.h +++ b/dom/src/jsurl/nsJSProtocolHandler.h @@ -63,6 +63,8 @@ protected: class nsJSURI : public nsSimpleURI { public: + using nsSimpleURI::Read; + using nsSimpleURI::Write; nsJSURI() {} diff --git a/dom/src/storage/Makefile.in b/dom/src/storage/Makefile.in index 2c9c771bf315..449ec3e978ab 100644 --- a/dom/src/storage/Makefile.in +++ b/dom/src/storage/Makefile.in @@ -7,6 +7,7 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/src/storage/nsDOMStorageMemoryDB.cpp b/dom/src/storage/nsDOMStorageMemoryDB.cpp index 8d3511f45b6c..94fba44c6e3c 100644 --- a/dom/src/storage/nsDOMStorageMemoryDB.cpp +++ b/dom/src/storage/nsDOMStorageMemoryDB.cpp @@ -339,8 +339,7 @@ nsDOMStorageMemoryDB::RemoveOwners(const nsTArray &aOwners, for (PRUint32 i = 0; i < aOwners.Length(); i++) { nsCAutoString quotaKey; - nsresult rv; - rv = nsDOMStorageDBWrapper::CreateDomainScopeDBKey( + nsDOMStorageDBWrapper::CreateDomainScopeDBKey( NS_ConvertUTF16toUTF8(aOwners[i]), quotaKey); if (!aIncludeSubDomains) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 34064dcac7f9..68d98ce8f55a 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -308,7 +308,7 @@ RadioInterfaceLayer.prototype = { onmessage: function onmessage(event) { let message = event.data; debug("Received message from worker: " + JSON.stringify(message)); - switch (message.type) { + switch (message.rilMessageType) { case "callStateChange": // This one will handle its own notifications. this.handleCallStateChange(message.call); @@ -434,7 +434,8 @@ RadioInterfaceLayer.prototype = { this.handleCancelUSSD(message); break; default: - throw new Error("Don't know about this message type: " + message.type); + throw new Error("Don't know about this message type: " + + message.rilMessageType); } }, @@ -1066,7 +1067,7 @@ RadioInterfaceLayer.prototype = { setRadioEnabled: function setRadioEnabled(value) { debug("Setting radio power to " + value); - this.worker.postMessage({type: "setRadioPower", on: value}); + this.worker.postMessage({rilMessageType: "setRadioPower", on: value}); }, rilContext: null, @@ -1075,72 +1076,84 @@ RadioInterfaceLayer.prototype = { enumerateCalls: function enumerateCalls() { debug("Requesting enumeration of calls for callback"); - this.worker.postMessage({type: "enumerateCalls"}); + this.worker.postMessage({rilMessageType: "enumerateCalls"}); }, dial: function dial(number) { debug("Dialing " + number); - this.worker.postMessage({type: "dial", number: number, isDialEmergency: false}); + this.worker.postMessage({rilMessageType: "dial", + number: number, + isDialEmergency: false}); }, dialEmergency: function dialEmergency(number) { debug("Dialing emergency " + number); - this.worker.postMessage({type: "dial", number: number, isDialEmergency: true}); + this.worker.postMessage({rilMessageType: "dial", + number: number, + isDialEmergency: true}); }, hangUp: function hangUp(callIndex) { debug("Hanging up call no. " + callIndex); - this.worker.postMessage({type: "hangUp", callIndex: callIndex}); + this.worker.postMessage({rilMessageType: "hangUp", + callIndex: callIndex}); }, startTone: function startTone(dtmfChar) { debug("Sending Tone for " + dtmfChar); - this.worker.postMessage({type: "startTone", dtmfChar: dtmfChar}); + this.worker.postMessage({rilMessageType: "startTone", + dtmfChar: dtmfChar}); }, stopTone: function stopTone() { debug("Stopping Tone"); - this.worker.postMessage({type: "stopTone"}); + this.worker.postMessage({rilMessageType: "stopTone"}); }, answerCall: function answerCall(callIndex) { - this.worker.postMessage({type: "answerCall", callIndex: callIndex}); + this.worker.postMessage({rilMessageType: "answerCall", + callIndex: callIndex}); }, rejectCall: function rejectCall(callIndex) { - this.worker.postMessage({type: "rejectCall", callIndex: callIndex}); + this.worker.postMessage({rilMessageType: "rejectCall", + callIndex: callIndex}); }, holdCall: function holdCall(callIndex) { - this.worker.postMessage({type: "holdCall", callIndex: callIndex}); + this.worker.postMessage({rilMessageType: "holdCall", + callIndex: callIndex}); }, resumeCall: function resumeCall(callIndex) { - this.worker.postMessage({type: "resumeCall", callIndex: callIndex}); + this.worker.postMessage({rilMessageType: "resumeCall", + callIndex: callIndex}); }, getAvailableNetworks: function getAvailableNetworks(requestId) { - this.worker.postMessage({type: "getAvailableNetworks", requestId: requestId}); + this.worker.postMessage({rilMessageType: "getAvailableNetworks", + requestId: requestId}); }, sendUSSD: function sendUSSD(message) { debug("SendUSSD " + JSON.stringify(message)); - message.type = "sendUSSD"; + message.rilMessageType = "sendUSSD"; this.worker.postMessage(message); }, cancelUSSD: function cancelUSSD(message) { debug("Cancel pending USSD"); - message.type = "cancelUSSD"; + message.rilMessageType = "cancelUSSD"; this.worker.postMessage(message); }, selectNetworkAuto: function selectNetworkAuto(requestId) { - this.worker.postMessage({type: "selectNetworkAuto", requestId: requestId}); + this.worker.postMessage({rilMessageType: "selectNetworkAuto", + requestId: requestId}); }, selectNetwork: function selectNetwork(message) { - message.type = "selectNetwork"; + message.rilMessageType = "selectNetwork"; this.worker.postMessage(message); }, @@ -1549,7 +1562,7 @@ RadioInterfaceLayer.prototype = { sendSMS: function sendSMS(number, message, requestId, processId) { let options = this._calculateUserDataLength(message); - options.type = "sendSMS"; + options.rilMessageType = "sendSMS"; options.number = number; options.requestId = requestId; options.processId = processId; @@ -1618,7 +1631,7 @@ RadioInterfaceLayer.prototype = { }, setupDataCall: function setupDataCall(radioTech, apn, user, passwd, chappap, pdptype) { - this.worker.postMessage({type: "setupDataCall", + this.worker.postMessage({rilMessageType: "setupDataCall", radioTech: radioTech, apn: apn, user: user, @@ -1628,20 +1641,20 @@ RadioInterfaceLayer.prototype = { }, deactivateDataCall: function deactivateDataCall(cid, reason) { - this.worker.postMessage({type: "deactivateDataCall", + this.worker.postMessage({rilMessageType: "deactivateDataCall", cid: cid, reason: reason}); }, getDataCallList: function getDataCallList() { - this.worker.postMessage({type: "getDataCallList"}); + this.worker.postMessage({rilMessageType: "getDataCallList"}); }, getCardLock: function getCardLock(message) { // Currently only support pin. switch (message.lockType) { case "pin" : - message.type = "getICCPinLock"; + message.rilMessageType = "getICCPinLock"; break; default: ppmm.sendAsyncMessage("RIL:GetCardLock:Return:KO", @@ -1655,16 +1668,16 @@ RadioInterfaceLayer.prototype = { unlockCardLock: function unlockCardLock(message) { switch (message.lockType) { case "pin": - message.type = "enterICCPIN"; + message.rilMessageType = "enterICCPIN"; break; case "pin2": - message.type = "enterICCPIN2"; + message.rilMessageType = "enterICCPIN2"; break; case "puk": - message.type = "enterICCPUK"; + message.rilMessageType = "enterICCPUK"; break; case "puk2": - message.type = "enterICCPUK2"; + message.rilMessageType = "enterICCPUK2"; break; default: ppmm.sendAsyncMessage("RIL:UnlockCardLock:Return:KO", @@ -1680,10 +1693,10 @@ RadioInterfaceLayer.prototype = { if (message.newPin !== undefined) { switch (message.lockType) { case "pin": - message.type = "changeICCPIN"; + message.rilMessageType = "changeICCPIN"; break; case "pin2": - message.type = "changeICCPIN2"; + message.rilMessageType = "changeICCPIN2"; break; default: ppmm.sendAsyncMessage("RIL:SetCardLock:Return:KO", @@ -1697,7 +1710,7 @@ RadioInterfaceLayer.prototype = { {errorMsg: "Unsupported Card Lock.", requestId: message.requestId}); } - message.type = "setICCPinLock"; + message.rilMessageType = "setICCPinLock"; } this.worker.postMessage(message); }, @@ -1722,7 +1735,7 @@ RadioInterfaceLayer.prototype = { debug("Unknown contact type. " + type); return; } - this.worker.postMessage({type: msgType, requestId: requestId}); + this.worker.postMessage({rilMessageType: msgType, requestId: requestId}); } }; diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp index 3444597ec051..a0c0bade1641 100644 --- a/dom/system/gonk/nsVolumeService.cpp +++ b/dom/system/gonk/nsVolumeService.cpp @@ -55,8 +55,11 @@ nsVolumeService::~nsVolumeService() /* nsIVolume getVolumeByName (in DOMString volName); */ NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVolume **aResult) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); nsRefPtr vol = FindVolumeByName(aVolName); if (!vol) { + ERR("GetVolumeByName: Unable to locate volume '%s'", + NS_LossyConvertUTF16toASCII(aVolName).get()); return NS_ERROR_NOT_AVAILABLE; } @@ -67,10 +70,12 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVol /* nsIVolume getVolumeByPath (in DOMString path); */ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume **aResult) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath); char realPathBuf[PATH_MAX]; if (!realpath(utf8Path.get(), realPathBuf)) { + ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno); return NSRESULT_FOR_ERRNO(); } @@ -96,11 +101,14 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume return NS_OK; } } + ERR("GetVolumeByPath: Unable to find volume by path: '%s'", + NS_LossyConvertUTF16toASCII(aPath).get()); return NS_ERROR_NOT_AVAILABLE; } already_AddRefed nsVolumeService::FindVolumeByName(const nsAString &aName) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(NS_IsMainThread()); nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); @@ -116,6 +124,7 @@ already_AddRefed nsVolumeService::FindVolumeByName(const nsAString &aN already_AddRefed nsVolumeService::FindAddVolumeByName(const nsAString &aName) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(NS_IsMainThread()); nsRefPtr vol; @@ -131,6 +140,7 @@ already_AddRefed nsVolumeService::FindAddVolumeByName(const nsAString void nsVolumeService::UpdateVolume(const nsVolume *aVolume) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(NS_IsMainThread()); nsRefPtr vol = FindAddVolumeByName(aVolume->Name()); diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 1c9f9940e60a..d5a642e2a8c6 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -610,6 +610,11 @@ let RIL = { */ iccInfo: {}, + /** + * Application identification for apps in ICC. + */ + aid: null, + voiceRegistrationState: {}, dataRegistrationState: {}, @@ -664,7 +669,7 @@ let RIL = { /** * Pending messages to be send in batch from requestNetworkInfo() */ - _pendingNetworkInfo: {type: "networkinfochanged"}, + _pendingNetworkInfo: {rilMessageType: "networkinfochanged"}, /** * Mute or unmute the radio. @@ -772,9 +777,9 @@ let RIL = { * Outgoing requests to the RIL. These can be triggered from the * main thread via messages that look like this: * - * {type: "methodName", - * extra: "parameters", - * go: "here"} + * {rilMessageType: "methodName", + * extra: "parameters", + * go: "here"} * * So if one of the following methods takes arguments, it takes only one, * an object, which then contains all of the parameters as attributes. @@ -793,11 +798,16 @@ let RIL = { * * @param pin * String containing the PIN. + * @param [optional] aid + * AID value. */ enterICCPIN: function enterICCPIN(options) { Buf.newParcel(REQUEST_ENTER_SIM_PIN, options); - Buf.writeUint32(1); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 1 : 2); Buf.writeString(options.pin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -806,11 +816,16 @@ let RIL = { * * @param pin * String containing the PIN2. + * @param [optional] aid + * AID value. */ enterICCPIN2: function enterICCPIN2(options) { Buf.newParcel(REQUEST_ENTER_SIM_PIN2, options); - Buf.writeUint32(1); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 1 : 2); Buf.writeString(options.pin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -821,12 +836,17 @@ let RIL = { * String containing the old PIN value * @param newPin * String containing the new PIN value + * @param [optional] aid + * AID value. */ changeICCPIN: function changeICCPIN(options) { Buf.newParcel(REQUEST_CHANGE_SIM_PIN, options); - Buf.writeUint32(2); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3); Buf.writeString(options.pin); Buf.writeString(options.newPin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -837,12 +857,17 @@ let RIL = { * String containing the old PIN2 value * @param newPin * String containing the new PIN2 value + * @param [optional] aid + * AID value. */ changeICCPIN2: function changeICCPIN2(options) { Buf.newParcel(REQUEST_CHANGE_SIM_PIN2, options); - Buf.writeUint32(2); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3); Buf.writeString(options.pin); Buf.writeString(options.newPin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, /** @@ -852,13 +877,17 @@ let RIL = { * String containing the PUK value. * @param newPin * String containing the new PIN value. - * + * @param [optional] aid + * AID value. */ enterICCPUK: function enterICCPUK(options) { Buf.newParcel(REQUEST_ENTER_SIM_PUK, options); - Buf.writeUint32(2); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3); Buf.writeString(options.puk); Buf.writeString(options.newPin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -869,13 +898,17 @@ let RIL = { * String containing the PUK2 value. * @param newPin * String containing the new PIN2 value. - * + * @param [optional] aid + * AID value. */ enterICCPUK2: function enterICCPUK2(options) { Buf.newParcel(REQUEST_ENTER_SIM_PUK2, options); - Buf.writeUint32(2); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3); Buf.writeString(options.puk); Buf.writeString(options.newPin); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -895,21 +928,26 @@ let RIL = { }, /** - * Query ICC facility lock. + * Query ICC facility lock. * - * @param facility - * One of ICC_CB_FACILITY_*. - * @param password - * Password for the facility, or "" if not required. - * @param serviceClass - * One of ICC_SERVICE_CLASS_*. + * @param facility + * One of ICC_CB_FACILITY_*. + * @param password + * Password for the facility, or "" if not required. + * @param serviceClass + * One of ICC_SERVICE_CLASS_*. + * @param [optional] aid + * AID value. */ queryICCFacilityLock: function queryICCFacilityLock(options) { Buf.newParcel(REQUEST_QUERY_FACILITY_LOCK, options); - Buf.writeUint32(3); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 3 : 4); Buf.writeString(options.facility); Buf.writeString(options.password); Buf.writeString(options.serviceClass.toString()); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -944,14 +982,19 @@ let RIL = { * Password for the facility, or "" if not required. * @param serviceClass * One of ICC_SERVICE_CLASS_*. + * @param [optional] aid + * AID value. */ setICCFacilityLock: function setICCFacilityLock(options) { Buf.newParcel(REQUEST_SET_FACILITY_LOCK, options); - Buf.writeUint32(4); + Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 3 : 4); Buf.writeString(options.facility); Buf.writeString(options.enabled ? "1" : "0"); Buf.writeString(options.password); Buf.writeString(options.serviceClass.toString()); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -972,10 +1015,10 @@ let RIL = { * Arbitrary integer parameters for the command. * @param data * String parameter for the command. - * @param pin2 [optional] + * @param pin2 * String containing the PIN2. - * @param aid - * String for the AID. + * @param [optional] aid + * AID value. */ iccIO: function iccIO(options) { let token = Buf.newParcel(REQUEST_SIM_IO, options); @@ -987,8 +1030,9 @@ let RIL = { Buf.writeUint32(options.p3); Buf.writeString(options.data); Buf.writeString(options.pin2 ? options.pin2 : null); - let appIndex = this.iccStatus.gsmUmtsSubscriptionAppIndex; - Buf.writeString(this.iccStatus.apps[appIndex].aid); + if (!RILQUIRKS_V5_LEGACY) { + Buf.writeString(options.aid ? options.aid : this.aid); + } Buf.sendParcel(); }, @@ -1007,19 +1051,24 @@ let RIL = { * Update the ICC information to RadioInterfaceLayer. */ _handleICCInfoChange: function _handleICCInfoChange() { - this.iccInfo.type = "iccinfochange"; + this.iccInfo.rilMessageType = "iccinfochange"; this.sendDOMMessage(this.iccInfo); }, - getIMSI: function getIMSI() { + /** + * Get IMSI. + * + * @param [optional] aid + * AID value. + */ + getIMSI: function getIMSI(aid) { if (RILQUIRKS_V5_LEGACY) { Buf.simpleRequest(REQUEST_GET_IMSI); return; } let token = Buf.newParcel(REQUEST_GET_IMSI); Buf.writeUint32(1); - let appIndex = this.iccStatus.gsmUmtsSubscriptionAppIndex; - Buf.writeString(this.iccStatus.apps[appIndex].aid); + Buf.writeString(aid ? aid : this.aid); Buf.sendParcel(); }, @@ -1234,7 +1283,7 @@ let RIL = { " number = " + this.iccInfo.fdn[i].number); } } - this.sendDOMMessage({type: "icccontacts", + this.sendDOMMessage({rilMessageType: "icccontacts", contactType: "FDN", contacts: this.iccInfo.fdn, requestId: options.requestId}); @@ -1279,7 +1328,7 @@ let RIL = { " number = " + this.iccInfo.adn[i].number); } } - this.sendDOMMessage({type: "icccontacts", + this.sendDOMMessage({rilMessageType: "icccontacts", contactType: "ADN", contacts: this.iccInfo.adn, requestId: options.requestId}); @@ -1317,7 +1366,7 @@ let RIL = { } if (this.iccInfo.mbdn != contact.number) { this.iccInfo.mbdn = contact.number; - contact.type = "iccmbdn"; + contact.rilMessageType = "iccmbdn"; this.sendDOMMessage(contact); } }; @@ -1557,7 +1606,7 @@ let RIL = { if (!this._isEmergencyNumber(options.number)) { // Notify error in establishing the call with an invalid number. options.callIndex = -1; - options.type = "callError"; + options.rilMessageType = "callError"; options.error = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER]; this.sendDOMMessage(options); @@ -1926,7 +1975,7 @@ let RIL = { return; } this.cardState = GECKO_CARDSTATE_ABSENT; - this.sendDOMMessage({type: "cardstatechange", + this.sendDOMMessage({rilMessageType: "cardstatechange", cardState: this.cardState}); return; } @@ -1941,7 +1990,7 @@ let RIL = { } this.cardState = GECKO_CARDSTATE_ABSENT; this.operator = null; - this.sendDOMMessage({type: "cardstatechange", + this.sendDOMMessage({rilMessageType: "cardstatechange", cardState: this.cardState}); return; } @@ -1970,13 +2019,18 @@ let RIL = { return; } + // TODO: Bug 726098, change to use cdmaSubscriptionAppIndex when in CDMA. + // fetchICCRecords will need to read aid, so read aid here. + let index = iccStatus.gsmUmtsSubscriptionAppIndex; + this.aid = iccStatus.apps[index].aid; + // This was moved down from CARD_APPSTATE_READY this.requestNetworkInfo(); this.getSignalStrength(); this.fetchICCRecords(); this.cardState = newCardState; - this.sendDOMMessage({type: "cardstatechange", + this.sendDOMMessage({rilMessageType: "cardstatechange", cardState: this.cardState}); }, @@ -2210,7 +2264,7 @@ let RIL = { } if (cellChanged) { - cell.type = "celllocationchanged"; + cell.rilMessageType = "celllocationchanged"; this.sendDOMMessage(cell); } @@ -2240,7 +2294,7 @@ let RIL = { } if (stateChanged) { - rs.type = "voiceregistrationstatechange"; + rs.rilMessageType = "voiceregistrationstatechange"; this._sendNetworkInfoMessage(NETWORK_INFO_VOICE_REGISTRATION_STATE, rs); } }, @@ -2262,7 +2316,7 @@ let RIL = { } if (stateChanged) { - rs.type = "dataregistrationstatechange"; + rs.rilMessageType = "dataregistrationstatechange"; this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs); } }, @@ -2275,7 +2329,7 @@ let RIL = { } if (!this.operator) { - this.operator = {type: "operatorchange"}; + this.operator = {rilMessageType: "operatorchange"}; } let [longName, shortName, networkTuple] = operatorData; @@ -2370,13 +2424,13 @@ let RIL = { }, _handleChangedCallState: function _handleChangedCallState(changedCall) { - let message = {type: "callStateChange", + let message = {rilMessageType: "callStateChange", call: changedCall}; this.sendDOMMessage(message); }, _handleDisconnectedCall: function _handleDisconnectedCall(disconnectedCall) { - let message = {type: "callDisconnected", + let message = {rilMessageType: "callDisconnected", call: disconnectedCall}; this.sendDOMMessage(message); }, @@ -2410,7 +2464,7 @@ let RIL = { if (!updatedDataCall) { delete this.currentDataCalls[currentDataCall.callIndex]; currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED; - currentDataCall.type = "datacallstatechange"; + currentDataCall.rilMessageType = "datacallstatechange"; this.sendDOMMessage(currentDataCall); continue; } @@ -2420,7 +2474,7 @@ let RIL = { currentDataCall.status = updatedDataCall.status; currentDataCall.active = updatedDataCall.active; currentDataCall.state = updatedDataCall.state; - currentDataCall.type = "datacallstatechange"; + currentDataCall.rilMessageType = "datacallstatechange"; this.sendDOMMessage(currentDataCall); } } @@ -2439,7 +2493,7 @@ let RIL = { } else if (DEBUG) { debug("Unexpected new data call: " + JSON.stringify(newDataCall)); } - newDataCall.type = "datacallstatechange"; + newDataCall.rilMessageType = "datacallstatechange"; this.sendDOMMessage(newDataCall); } }, @@ -2582,7 +2636,7 @@ let RIL = { } if (message) { - message.type = "sms-received"; + message.rilMessageType = "sms-received"; this.sendDOMMessage(message); } @@ -2645,7 +2699,7 @@ let RIL = { } else { // Last segment delivered with success. Report it. this.sendDOMMessage({ - type: "sms-delivered", + rilMessageType: "sms-delivered", envelopeId: options.envelopeId, }); } @@ -2747,7 +2801,7 @@ let RIL = { */ handleDOMMessage: function handleMessage(message) { if (DEBUG) debug("Received DOM message " + JSON.stringify(message)); - let method = this[message.type]; + let method = this[message.rilMessageType]; if (typeof method != "function") { if (DEBUG) { debug("Don't know what to do with message " + JSON.stringify(message)); @@ -2766,7 +2820,7 @@ let RIL = { for each (let call in this.currentCalls) { calls.push(call); } - this.sendDOMMessage({type: "enumerateCalls", calls: calls}); + this.sendDOMMessage({rilMessageType: "enumerateCalls", calls: calls}); }, /** @@ -2777,7 +2831,7 @@ let RIL = { for each (let datacall in this.currentDataCalls) { datacall_list.push(datacall); } - this.sendDOMMessage({type: "datacalllist", + this.sendDOMMessage({rilMessageType: "datacalllist", datacalls: datacall_list}); }, @@ -2846,42 +2900,42 @@ RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) { this._processICCStatus(iccStatus); }; RIL[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) { - this.sendDOMMessage({type: "iccunlockcardlock", + this.sendDOMMessage({rilMessageType: "iccunlockcardlock", lockType: "pin", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, requestId: options.requestId}); }; RIL[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) { - this.sendDOMMessage({type: "iccunlockcardlock", + this.sendDOMMessage({rilMessageType: "iccunlockcardlock", lockType: "puk", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, requestId: options.requestId}); }; RIL[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) { - this.sendDOMMessage({type: "iccunlockcardlock", + this.sendDOMMessage({rilMessageType: "iccunlockcardlock", lockType: "pin2", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, requestId: options.requestId}); }; RIL[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) { - this.sendDOMMessage({type: "iccunlockcardlock", + this.sendDOMMessage({rilMessageType: "iccunlockcardlock", lockType: "puk2", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, requestId: options.requestId}); }; RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) { - this.sendDOMMessage({type: "iccsetcardlock", + this.sendDOMMessage({rilMessageType: "iccsetcardlock", lockType: "pin", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, requestId: options.requestId}); }; RIL[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) { - this.sendDOMMessage({type: "iccsetcardlock", + this.sendDOMMessage({rilMessageType: "iccsetcardlock", lockType: "pin2", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, @@ -3027,7 +3081,7 @@ RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length case CALL_FAIL_IMSI_UNKNOWN_IN_VLR: case CALL_FAIL_IMEI_NOT_ACCEPTED: case CALL_FAIL_ERROR_UNSPECIFIED: - options.type = "callError"; + options.rilMessageType = "callError"; options.error = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[failCause]; this.sendDOMMessage(options); break; @@ -3093,7 +3147,7 @@ RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) } if (DEBUG) debug("Signal strength " + JSON.stringify(obj)); - obj.type = "signalstrengthchange"; + obj.rilMessageType = "signalstrengthchange"; this.sendDOMMessage(obj); }; RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) { @@ -3148,7 +3202,7 @@ RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { // Fallback to default error handling if it meets max retry count. default: this.sendDOMMessage({ - type: "sms-send-failed", + rilMessageType: "sms-send-failed", envelopeId: options.envelopeId, error: options.rilRequestError, }); @@ -3175,7 +3229,7 @@ RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { } else { // Last segment sent with success. Report it. this.sendDOMMessage({ - type: "sms-sent", + rilMessageType: "sms-sent", envelopeId: options.envelopeId, }); } @@ -3199,7 +3253,7 @@ RIL.readSetupDataCall_v5 = function readSetupDataCall_v5(options) { RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) { if (options.rilRequestError) { - options.type = "datacallerror"; + options.rilMessageType = "datacallerror"; this.sendDOMMessage(options); return; } @@ -3209,7 +3263,7 @@ RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) // we retain the APN and other info about how the data call was set up. this.readSetupDataCall_v5(options); this.currentDataCalls[options.cid] = options; - options.type = "datacallstatechange"; + options.rilMessageType = "datacallstatechange"; this.sendDOMMessage(options); // Let's get the list of data calls to ensure we know whether it's active // or not. @@ -3241,7 +3295,7 @@ RIL[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) { if (DEBUG) { debug("REQUEST_SEND_USSD " + JSON.stringify(options)); } - options.type = "sendussd"; + options.rilMessageType = "sendussd"; options.success = options.rilRequestError == 0 ? true : false; this.sendDOMMessage(options); }; @@ -3249,7 +3303,7 @@ RIL[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) { if (DEBUG) { debug("REQUEST_CANCEL_USSD" + JSON.stringify(options)); } - options.type = "cancelussd"; + options.rilMessageType = "cancelussd"; options.success = options.rilRequestError == 0 ? true : false; this.sendDOMMessage(options); }; @@ -3283,7 +3337,7 @@ RIL[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length let datacall = this.currentDataCalls[options.cid]; delete this.currentDataCalls[options.cid]; datacall.state = GECKO_NETWORK_STATE_DISCONNECTED; - datacall.type = "datacallstatechange"; + datacall.rilMessageType = "datacallstatechange"; this.sendDOMMessage(datacall); }; RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) { @@ -3292,13 +3346,13 @@ RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, } let response = Buf.readUint32List()[0]; - this.sendDOMMessage({type: "iccgetcardlock", + this.sendDOMMessage({rilMessageType: "iccgetcardlock", lockType: "pin", enabled: response == 0 ? false : true, requestId: options.requestId}); }; RIL[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) { - this.sendDOMMessage({type: "iccsetcardlock", + this.sendDOMMessage({rilMessageType: "iccsetcardlock", lockType: "pin", result: options.rilRequestError == 0 ? true : false, retryCount: length ? Buf.readUint32List()[0] : -1, @@ -3331,7 +3385,7 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELEC if (this.mode != selectionMode) { this.mode = options.mode = selectionMode; - options.type = "networkselectionmodechange"; + options.rilMessageType = "networkselectionmodechange"; this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options); } }; @@ -3549,7 +3603,7 @@ RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RA this.radioState = newState; this.sendDOMMessage({ - type: "radiostatechange", + rilMessageType: "radiostatechange", radioState: newState }); @@ -3590,7 +3644,7 @@ RIL[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() { if (!message || message == "") { return; } - this.sendDOMMessage({type: "ussdreceived", + this.sendDOMMessage({rilMessageType: "ussdreceived", message: message}); }; RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() { @@ -3625,7 +3679,7 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() return; } - this.sendDOMMessage({type: "nitzTime", + this.sendDOMMessage({rilMessageType: "nitzTime", networkTimeInSeconds: timeInSeconds, networkTimeZoneInMinutes: tz * 15, dstFlag: dst, diff --git a/dom/telephony/Telephony.cpp b/dom/telephony/Telephony.cpp index 1c6e66fe14c2..a65c3eacc62e 100644 --- a/dom/telephony/Telephony.cpp +++ b/dom/telephony/Telephony.cpp @@ -11,7 +11,7 @@ #include "nsPIDOMWindow.h" #include "jsapi.h" -#include "mozilla/Preferences.h" +#include "nsIPermissionManager.h" #include "nsCharSeparatedTokenizer.h" #include "nsContentUtils.h" #include "nsDOMClassInfo.h" @@ -26,9 +26,6 @@ USING_TELEPHONY_NAMESPACE using namespace mozilla::dom::gonk; -using mozilla::Preferences; - -#define DOM_TELEPHONY_APP_PHONE_URL_PREF "dom.telephony.app.phone.url" namespace { @@ -547,15 +544,24 @@ NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony) aWindow : aWindow->GetCurrentInnerWindow(); + // Need the document for security check. + nsCOMPtr document = + do_QueryInterface(innerWindow->GetExtantDocument()); + NS_ENSURE_TRUE(document, NS_NOINTERFACE); - bool allowed; + nsCOMPtr principal = document->NodePrincipal(); + NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED); + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED); + + PRUint32 permission; nsresult rv = - nsContentUtils::IsOnPrefWhitelist(innerWindow, - DOM_TELEPHONY_APP_PHONE_URL_PREF, - &allowed); + permMgr->TestPermissionFromPrincipal(principal, "telephony", &permission); NS_ENSURE_SUCCESS(rv, rv); - - if (!allowed) { + + if (permission != nsIPermissionManager::ALLOW_ACTION) { *aTelephony = nullptr; return NS_OK; } diff --git a/dom/telephony/test/marionette/test_emergency.js b/dom/telephony/test/marionette/test_emergency.js index b73a03857baf..ff4169eb656d 100644 --- a/dom/telephony/test/marionette/test_emergency.js +++ b/dom/telephony/test/marionette/test_emergency.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "911"; @@ -92,7 +91,7 @@ function hangUp() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_emergency_badNumber.js b/dom/telephony/test/marionette/test_emergency_badNumber.js index 37fafb75e62a..0bdaf393294d 100644 --- a/dom/telephony/test/marionette/test_emergency_badNumber.js +++ b/dom/telephony/test/marionette/test_emergency_badNumber.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "not a valid emergency number"; @@ -57,7 +56,7 @@ function dial() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_incoming_answer_hangup.js b/dom/telephony/test/marionette/test_incoming_answer_hangup.js index eeb19102f00e..73e35713466a 100644 --- a/dom/telephony/test/marionette/test_incoming_answer_hangup.js +++ b/dom/telephony/test/marionette/test_incoming_answer_hangup.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -109,7 +108,7 @@ function hangUp() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js b/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js index d311e9339bc0..bd770d2080a3 100644 --- a/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js +++ b/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -128,7 +127,7 @@ function hangUp() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_incoming_reject.js b/dom/telephony/test/marionette/test_incoming_reject.js index 815a1a3e35ac..1a4ef16864f9 100644 --- a/dom/telephony/test/marionette/test_incoming_reject.js +++ b/dom/telephony/test/marionette/test_incoming_reject.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -80,7 +79,7 @@ function reject() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_answer_hangup.js b/dom/telephony/test/marionette/test_outgoing_answer_hangup.js index ce9dcddeaeba..96ec5cfcaf59 100644 --- a/dom/telephony/test/marionette/test_outgoing_answer_hangup.js +++ b/dom/telephony/test/marionette/test_outgoing_answer_hangup.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -92,7 +91,7 @@ function hangUp() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js b/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js index d9b2657aa7a4..ce4df9f190b5 100644 --- a/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js +++ b/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -94,7 +93,7 @@ function hangUp() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_badNumber.js b/dom/telephony/test/marionette/test_outgoing_badNumber.js index 951470a3c68c..f869e2c7b041 100644 --- a/dom/telephony/test/marionette/test_outgoing_badNumber.js +++ b/dom/telephony/test/marionette/test_outgoing_badNumber.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "not a valid phone number"; @@ -54,7 +53,7 @@ function dial() { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_busy.js b/dom/telephony/test/marionette/test_outgoing_busy.js index 1b4f57a5ec89..5d3301d71f1f 100644 --- a/dom/telephony/test/marionette/test_outgoing_busy.js +++ b/dom/telephony/test/marionette/test_outgoing_busy.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -71,7 +70,7 @@ function busy() { }; function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js b/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js index 1e325f9bd898..8e06e48737a8 100644 --- a/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js +++ b/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -82,7 +81,7 @@ function hangUp() { }; function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_hangup_held.js b/dom/telephony/test/marionette/test_outgoing_hangup_held.js index 079169b31eb2..d4dd3058b56b 100644 --- a/dom/telephony/test/marionette/test_outgoing_hangup_held.js +++ b/dom/telephony/test/marionette/test_outgoing_hangup_held.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -145,7 +144,7 @@ function cmdCallback(result) { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/telephony/test/marionette/test_outgoing_reject.js b/dom/telephony/test/marionette/test_outgoing_reject.js index 71e184322ce0..2195917fb705 100644 --- a/dom/telephony/test/marionette/test_outgoing_reject.js +++ b/dom/telephony/test/marionette/test_outgoing_reject.js @@ -3,8 +3,7 @@ MARIONETTE_TIMEOUT = 10000; -const WHITELIST_PREF = "dom.telephony.app.phone.url"; -SpecialPowers.setCharPref(WHITELIST_PREF, window.location.href); +SpecialPowers.addPermission("telephony", true, document); let telephony = window.navigator.mozTelephony; let number = "5555552368"; @@ -83,7 +82,7 @@ function cmdCallback(result) { } function cleanUp() { - SpecialPowers.clearUserPref(WHITELIST_PREF); + SpecialPowers.removePermission("telephony", document); finish(); } diff --git a/dom/workers/Makefile.in b/dom/workers/Makefile.in index cc07238df20b..1f52752a19fd 100644 --- a/dom/workers/Makefile.in +++ b/dom/workers/Makefile.in @@ -1,11 +1,12 @@ # 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/. +# 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/. DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ +FAIL_ON_WARNINGS := 1 include $(DEPTH)/config/autoconf.mk diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 41c9f6b174f2..2a8729aa6811 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -65,7 +65,8 @@ using mozilla::Preferences; // The maximum number of threads to use for workers, overridable via pref. #define MAX_WORKERS_PER_DOMAIN 10 -PR_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1); +MOZ_STATIC_ASSERT(MAX_WORKERS_PER_DOMAIN >= 1, + "We should allow at least one worker per domain."); // The default number of seconds that close handlers will be allowed to run. #define MAX_SCRIPT_RUN_TIME_SEC 10 @@ -139,7 +140,8 @@ const char* gStringChars[] = { // thread. }; -PR_STATIC_ASSERT(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT); +MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT, + "gStringChars should have the right length."); enum { PREF_strict = 0, @@ -179,7 +181,8 @@ const char* gPrefsToWatch[] = { #endif }; -PR_STATIC_ASSERT(NS_ARRAY_LENGTH(gPrefsToWatch) == PREF_COUNT); +MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(gPrefsToWatch) == PREF_COUNT, + "gPrefsToWatch should have the right length."); int PrefCallback(const char* aPrefName, void* aClosure) diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 83cab00b559d..8b8314d00480 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -35,6 +35,8 @@ #include "WorkerFeature.h" #include "WorkerPrivate.h" +#include "nsDOMError.h" + #define MAX_CONCURRENT_SCRIPTS 1000 USING_WORKERS_NAMESPACE diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 1b94bf4e72b3..3cdfe1226693 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -31,6 +31,7 @@ #include "js/MemoryMetrics.h" #include "nsAlgorithm.h" #include "nsContentUtils.h" +#include "nsDOMError.h" #include "nsDOMJSUtils.h" #include "nsGUIEvent.h" #include "nsJSEnvironment.h" @@ -945,9 +946,6 @@ public: JSObject* target = aWorkerPrivate->IsAcceptingEvents() ? aWorkerPrivate->GetJSObject() : nullptr; - if (target) { - aWorkerPrivate->AssertInnerWindowIsCorrect(); - } PRUint64 innerWindowId; @@ -963,6 +961,8 @@ public: return true; } + aWorkerPrivate->AssertInnerWindowIsCorrect(); + innerWindowId = aWorkerPrivate->GetInnerWindowId(); } diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 18863813e4da..57dd3445819c 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -961,8 +961,11 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx) if (worker->IsChromeWorker() && (!chromeworker::InitClass(aCx, global, workerProto, false) || - !DefineChromeWorkerFunctions(aCx, global)) || - !DefineOSFileConstants(aCx, global)) { + !DefineChromeWorkerFunctions(aCx, global))) { + return NULL; + } + + if (!DefineOSFileConstants(aCx, global)) { return NULL; } diff --git a/embedding/tests/winEmbed/winEmbed.cpp b/embedding/tests/winEmbed/winEmbed.cpp index 3285eba961be..d29f7a2327d4 100644 --- a/embedding/tests/winEmbed/winEmbed.cpp +++ b/embedding/tests/winEmbed/winEmbed.cpp @@ -874,7 +874,7 @@ void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome) // Clear the window user data HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); - SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, nullptr); + SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, 0); DestroyWindow(hwndBrowser); DestroyWindow(hwndDlg); diff --git a/gfx/2d/Blur.cpp b/gfx/2d/Blur.cpp index 39c39b156a93..86ba47aa9cd7 100644 --- a/gfx/2d/Blur.cpp +++ b/gfx/2d/Blur.cpp @@ -9,12 +9,9 @@ #include #include "mozilla/CheckedInt.h" +#include "mozilla/Constants.h" #include "mozilla/Util.h" -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - using namespace std; namespace mozilla { diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 56ac8c7f0615..d955baebed98 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -14,13 +14,10 @@ #include "Logging.h" #include "Tools.h" #include +#include "mozilla/Constants.h" #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( D2D1_FACTORY_TYPE factoryType, REFIID iid, diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index 41681fcf9a6a..5c9f50163aad 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -8,10 +8,7 @@ #include #include "DrawTargetD2D.h" #include "Logging.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif +#include "mozilla/Constants.h" namespace mozilla { namespace gfx { diff --git a/gfx/2d/PathHelpers.h b/gfx/2d/PathHelpers.h index d6434607659d..19759207a93e 100644 --- a/gfx/2d/PathHelpers.h +++ b/gfx/2d/PathHelpers.h @@ -7,10 +7,7 @@ #define MOZILLA_GFX_PATHHELPERS_H_ #include "2D.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif +#include "mozilla/Constants.h" namespace mozilla { namespace gfx { diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index 6ac266070ffb..e09e305a7e5c 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -276,8 +276,10 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface) int attribs[] = { GLX_DOUBLEBUFFER, False, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_ALPHA_SIZE, (withAlpha ? 1 : 0), (withAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT), True, + GLX_RENDER_TYPE, GLX_RGBA_BIT, None }; int numConfigs = 0; @@ -297,18 +299,24 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface) static_cast(direct.greenMask) << direct.green; unsigned long blueMask = static_cast(direct.blueMask) << direct.blue; + // XVisualInfo doesn't have information on the alpha channel, so just + // check the number of bits. + int alphaSize; + PR_FLOOR_LOG2(alphaSize, direct.alphaMask + 1); + NS_ASSERTION((1 << alphaSize) - 1 == direct.alphaMask, + "Unexpected render format with non-adjacent alpha bits"); ScopedXFree vinfo; for (int i = 0; i < numConfigs; i++) { int size; - // The visual depth won't necessarily match as it may not include the - // alpha buffer, so check buffer size. if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], - GLX_BUFFER_SIZE, &size) != Success || - size != format->depth) { + GLX_ALPHA_SIZE, &size) != Success || + size != alphaSize) { continue; } + // The visual depth won't necessarily match the render format depth as + // it may not include the alpha channel. vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]); if (!vinfo || vinfo->c_class != TrueColor || diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh index 4c89a8fcc16d..f222c073534e 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh @@ -38,7 +38,7 @@ enum hb_ot_shape_normalization_mode_t { HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL, /* including base-to-base composition */ - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS }; HB_INTERNAL void _hb_ot_shape_normalize (hb_font_t *font, diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 7ac951dbdd90..7972f567bbff 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -6,6 +6,7 @@ #include "CompositorParent.h" #include "mozilla/gfx/2D.h" +#include "mozilla/Constants.h" #include "mozilla/Util.h" #include "mozilla/XPCOM.h" #include "mozilla/Monitor.h" @@ -18,10 +19,6 @@ namespace mozilla { namespace layers { -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - static const float EPSILON = 0.0001; /** diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 0f9b6ccb672e..1a3a4e74c556 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -8,9 +8,7 @@ #endif #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif +#include "mozilla/Constants.h" #include "cairo.h" diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index 94d70a5b3e0b..9ddcad68d138 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -1194,14 +1194,12 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext, // in our clump; if not, we have a discontinuous range, and should extend it // unless we've reached the end of the text bool allGlyphsAreWithinCluster = true; - PRInt32 prevGlyphCharIndex = charStart - 1; for (PRInt32 i = glyphStart; i < glyphEnd; ++i) { PRInt32 glyphCharIndex = ginfo[i].cluster; if (glyphCharIndex < charStart || glyphCharIndex >= charEnd) { allGlyphsAreWithinCluster = false; break; } - prevGlyphCharIndex = glyphCharIndex; } if (allGlyphsAreWithinCluster) { break; diff --git a/image/src/SVGDocumentWrapper.cpp b/image/src/SVGDocumentWrapper.cpp index 3fe5afc71bab..7b794055b7f7 100644 --- a/image/src/SVGDocumentWrapper.cpp +++ b/image/src/SVGDocumentWrapper.cpp @@ -23,6 +23,7 @@ #include "nsIXMLContentSink.h" #include "nsNetCID.h" #include "nsComponentManagerUtils.h" +#include "nsSMILAnimationController.h" #include "nsServiceManagerUtils.h" #include "nsSize.h" #include "gfxRect.h" diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 39b88e95bd5e..bb0b210f173e 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -563,29 +563,6 @@ distclean clean:: endif endif -# Because the SpiderMonkey can be distributed and built independently -# of the Mozilla source tree, it contains its own copies of many of -# the files used by the top-level Mozilla build process, from the -# 'config' and 'build' subtrees. -# -# To make it simpler to keep the copies in sync, we follow the policy -# that the SpiderMonkey copies must always be exact copies of those in -# the containing Mozilla tree. If you've made a change in one, it -# belongs in the other as well. If the change isn't right for both -# places, then that's something to bring up with the other developers. -# -# Some files are reasonable to diverge; for example, -# js/config/autoconf.mk.in doesn't need most of the stuff in -# config/autoconf.mk.in. -check-sync-dirs-cmd = $(PYTHON) $(srcdir)/config/check-sync-dirs.py -check-sync-dirs: - $(check-sync-dirs-cmd) $(srcdir)/config $(MOZ_SYNC_BUILD_FILES)/config - $(check-sync-dirs-cmd) $(srcdir)/build $(MOZ_SYNC_BUILD_FILES)/build - -ifdef MOZ_SYNC_BUILD_FILES -check:: check-sync-dirs -endif - # The "find any vanilla new/new[] calls" script is tailored to Linux, so # only run it there. That should be enough to catch any such calls that # creep in. diff --git a/js/src/MemoryMetrics.cpp b/js/src/MemoryMetrics.cpp index ffe939a086f2..f77aa261f46f 100644 --- a/js/src/MemoryMetrics.cpp +++ b/js/src/MemoryMetrics.cpp @@ -22,11 +22,17 @@ namespace JS { using namespace js; +typedef HashSet, SystemAllocPolicy> SourceSet; + struct IteratorClosure { RuntimeStats *rtStats; ObjectPrivateVisitor *opv; + SourceSet seenSources; IteratorClosure(RuntimeStats *rt, ObjectPrivateVisitor *v) : rtStats(rt), opv(v) {} + bool init() { + return seenSources.init(); + } }; size_t @@ -177,6 +183,13 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin cStats->mjitData += script->ion->size(); # endif #endif + + ScriptSource *ss = script->scriptSource(); + SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss); + if (!entry) { + closure->seenSources.add(entry, ss); // Not much to be done on failure. + rtStats->runtime.scriptSources += ss->sizeOfIncludingThis(rtStats->mallocSizeOf); + } break; } case JSTRACE_IONCODE: @@ -217,6 +230,9 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor * // Take the per-compartment measurements. IteratorClosure closure(rtStats, opv); + if (!closure.init()) + return false; + rtStats->runtime.scriptSources = 0; IterateCompartmentsArenasCells(rt, &closure, StatsCompartmentCallback, StatsArenaCallback, StatsCellCallback); diff --git a/js/src/build/ConfigStatus.py b/js/src/build/ConfigStatus.py index 6b53b07c2380..2da626a34053 100644 --- a/js/src/build/ConfigStatus.py +++ b/js/src/build/ConfigStatus.py @@ -99,28 +99,32 @@ class ConfigEnvironment(object): directory. It preprocesses files from the source directory and stores the result in the object directory. - There are two types of files: config files and config headers, - each treated through a different member function. + There are two types of files: config files and config headers, + each treated through a different member function. - Creating a ConfigEnvironment requires a few arguments: - - topsrcdir and topobjdir are, respectively, the top source and - the top object directory. - - defines is a list of (name, value) tuples. In autoconf, these are - set with AC_DEFINE and AC_DEFINE_UNQUOTED - - non_global_defines are a list of names appearing in defines above - that are not meant to be exported in ACDEFINES and ALLDEFINES (see - below) - - substs is a list of (name, value) tuples. In autoconf, these are - set with AC_SUBST. + Creating a ConfigEnvironment requires a few arguments: + - topsrcdir and topobjdir are, respectively, the top source and + the top object directory. + - defines is a list of (name, value) tuples. In autoconf, these are + set with AC_DEFINE and AC_DEFINE_UNQUOTED + - non_global_defines are a list of names appearing in defines above + that are not meant to be exported in ACDEFINES and ALLDEFINES (see + below) + - substs is a list of (name, value) tuples. In autoconf, these are + set with AC_SUBST. - ConfigEnvironment automatically defines two additional substs variables - from all the defines not appearing in non_global_defines: - - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on - preprocessor command lines. The order in which defines were given - when creating the ConfigEnvironment is preserved. - - ALLDEFINES contains the defines in the form #define NAME VALUE, in - sorted order, for use in config files, for an automatic listing of - defines. + ConfigEnvironment automatically defines two additional substs variables + from all the defines not appearing in non_global_defines: + - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on + preprocessor command lines. The order in which defines were given + when creating the ConfigEnvironment is preserved. + - ALLDEFINES contains the defines in the form #define NAME VALUE, in + sorted order, for use in config files, for an automatic listing of + defines. + and another additional subst variable from all the other substs: + - ALLSUBSTS contains the substs in the form NAME = VALUE, in sorted + order, for use in autoconf.mk. It includes ACDEFINES, but doesn't + include ALLDEFINES. ConfigEnvironment expects a "top_srcdir" subst to be set with the top source directory, in msys format on windows. It is used to derive a @@ -136,6 +140,7 @@ class ConfigEnvironment(object): self.topobjdir = topobjdir global_defines = [name for name, value in defines if not name in non_global_defines] self.substs['ACDEFINES'] = ' '.join(["-D%s=%s" % (name, shell_escape(self.defines[name])) for name in global_defines]) + self.substs['ALLSUBSTS'] = '\n'.join(sorted(["%s = %s" % (name, self.substs[name]) for name in self.substs])) self.substs['ALLDEFINES'] = '\n'.join(sorted(["#define %s %s" % (name, self.defines[name]) for name in global_defines])) def get_relative_srcdir(self, file): diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index 23a6351421ff..e8b9866b590b 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -170,7 +170,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c args.rval().set(args[0]); return true; } - JSString *str = args[0].toString(); + RootedString str(cx, args[0].toString()); // ES5 15.1.2.1 steps 2-8. diff --git a/js/src/config/autoconf.mk.in b/js/src/config/autoconf.mk.in index b2f82b6df083..3a1f0d8f49e1 100644 --- a/js/src/config/autoconf.mk.in +++ b/js/src/config/autoconf.mk.in @@ -1,286 +1,2 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# A netscape style .mk file for autoconf builds - -target = @target@ -ac_configure_args = @ac_configure_args@ -MOZILLA_VERSION = @MOZILLA_VERSION@ - -MOZ_APP_NAME = @MOZ_APP_NAME@ -MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@ -MOZ_APP_VERSION = @MOZ_APP_VERSION@ - -MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -includedir = @includedir@ -libdir = @libdir@ -datadir = @datadir@ -mandir = @mandir@ - -TOP_DIST = @TOP_DIST@ - -MOZ_JS_LIBS = @MOZ_JS_LIBS@ - -MOZ_SYNC_BUILD_FILES = @MOZ_SYNC_BUILD_FILES@ - -MOZ_DEBUG = @MOZ_DEBUG@ -MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@ -MOZ_DEBUG_ENABLE_DEFS = @MOZ_DEBUG_ENABLE_DEFS@ -MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@ -MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@ -MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@ -MOZ_MEMORY = @MOZ_MEMORY@ -MOZ_PROFILING = @MOZ_PROFILING@ -MOZ_JPROF = @MOZ_JPROF@ -MOZ_SHARK = @MOZ_SHARK@ -MOZ_VALGRIND = @MOZ_VALGRIND@ -MOZ_CALLGRIND = @MOZ_CALLGRIND@ -MOZ_VTUNE = @MOZ_VTUNE@ -MOZ_ETW = @MOZ_ETW@ -JS_HAS_CTYPES = @JS_HAS_CTYPES@ -DEHYDRA_PATH = @DEHYDRA_PATH@ - -MOZ_USING_CCACHE = @MOZ_USING_CCACHE@ -CLANG_CXX = @CLANG_CXX@ -NS_TRACE_MALLOC = @NS_TRACE_MALLOC@ -INCREMENTAL_LINKER = @INCREMENTAL_LINKER@ -MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@ -ENABLE_TESTS = @ENABLE_TESTS@ - -# The MOZ_UI_LOCALE var is used to build a particular locale. Do *not* -# use the var to change any binary files. Do *not* use this var unless you -# write rules for the "clean-locale" and "locale" targets. -MOZ_UI_LOCALE = @MOZ_UI_LOCALE@ - -MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@ -MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@ - -MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@ - -ENABLE_STRIP = @ENABLE_STRIP@ -PKG_SKIP_STRIP = @PKG_SKIP_STRIP@ - -MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO_LIB_COMMAND@ -MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@ - -MOZ_BUILD_ROOT = @MOZ_BUILD_ROOT@ - -MOZ_NATIVE_NSPR = @MOZ_NATIVE_NSPR@ - -CROSS_COMPILE = @CROSS_COMPILE@ - -OS_CPPFLAGS = @OS_CPPFLAGS@ -OS_CFLAGS = @OS_CFLAGS@ -OS_CXXFLAGS = @OS_CXXFLAGS@ -OS_LDFLAGS = @OS_LDFLAGS@ - -OS_COMPILE_CFLAGS = @OS_COMPILE_CFLAGS@ -OS_COMPILE_CXXFLAGS = @OS_COMPILE_CXXFLAGS@ - -OS_LIBS = @OS_LIBS@ -ACDEFINES = @ACDEFINES@ - -WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@ -FAIL_ON_WARNINGS = @FAIL_ON_WARNINGS@ - -MOZ_OPTIMIZE = @MOZ_OPTIMIZE@ -MOZ_FRAMEPTR_FLAGS = @MOZ_FRAMEPTR_FLAGS@ -MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@ -MOZ_PGO_OPTIMIZE_FLAGS = @MOZ_PGO_OPTIMIZE_FLAGS@ -MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@ -MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@ - -PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@ -PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@ -PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@ -PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@ - -WIN_TOP_SRC = @WIN_TOP_SRC@ -AR = @AR@ -AR_FLAGS = @AR_FLAGS@ -AR_EXTRACT = @AR_EXTRACT@ -AR_LIST = @AR_LIST@ -AR_DELETE = @AR_DELETE@ -AS = @AS@ -ASFLAGS = @ASFLAGS@ -AS_DASH_C_FLAG = @AS_DASH_C_FLAG@ -LD = @LD@ -RC = @RC@ -RCFLAGS = @RCFLAGS@ -MC = @MC@ -WINDRES = @WINDRES@ -IMPLIB = @IMPLIB@ -FILTER = @FILTER@ -BIN_FLAGS = @BIN_FLAGS@ -_MSC_VER = @_MSC_VER@ - -DLL_PREFIX = @DLL_PREFIX@ -LIB_PREFIX = @LIB_PREFIX@ -OBJ_SUFFIX = @OBJ_SUFFIX@ -LIB_SUFFIX = @LIB_SUFFIX@ -DLL_SUFFIX = @DLL_SUFFIX@ -BIN_SUFFIX = @BIN_SUFFIX@ -ASM_SUFFIX = @ASM_SUFFIX@ -IMPORT_LIB_SUFFIX = @IMPORT_LIB_SUFFIX@ -LIBS_DESC_SUFFIX = @LIBS_DESC_SUFFIX@ -USE_N32 = @USE_N32@ -HAVE_64BIT_OS = @HAVE_64BIT_OS@ - -CC = @CC@ -CXX = @CXX@ -CPP = @CPP@ - -CC_VERSION = @CC_VERSION@ -CXX_VERSION = @CXX_VERSION@ - -GNU_AS = @GNU_AS@ -GNU_LD = @GNU_LD@ -GNU_CC = @GNU_CC@ -GNU_CXX = @GNU_CXX@ -INTEL_CC = @INTEL_CC@ -INTEL_CXX = @INTEL_CXX@ - -HOST_CC = @HOST_CC@ -HOST_CXX = @HOST_CXX@ -HOST_CFLAGS = @HOST_CFLAGS@ -HOST_CXXFLAGS = @HOST_CXXFLAGS@ -HOST_LDFLAGS = @HOST_LDFLAGS@ -HOST_OPTIMIZE_FLAGS = @HOST_OPTIMIZE_FLAGS@ -HOST_NSPR_MDCPUCFG = @HOST_NSPR_MDCPUCFG@ -HOST_AR = @HOST_AR@ -HOST_AR_FLAGS = @HOST_AR_FLAGS@ -HOST_LD = @HOST_LD@ -HOST_RANLIB = @HOST_RANLIB@ -HOST_BIN_SUFFIX = @HOST_BIN_SUFFIX@ - -HOST_OS_ARCH = @HOST_OS_ARCH@ -host_cpu = @host_cpu@ -host_vendor = @host_vendor@ -host_os = @host_os@ - -TARGET_NSPR_MDCPUCFG = @TARGET_NSPR_MDCPUCFG@ -TARGET_CPU = @TARGET_CPU@ -TARGET_VENDOR = @TARGET_VENDOR@ -TARGET_OS = @TARGET_OS@ -TARGET_MD_ARCH = @TARGET_MD_ARCH@ -TARGET_XPCOM_ABI = @TARGET_XPCOM_ABI@ - -AUTOCONF = @AUTOCONF@ -PERL = @PERL@ -PYTHON = @PYTHON@ -RANLIB = @RANLIB@ -XARGS = @XARGS@ -STRIP = @STRIP@ -DOXYGEN = @DOXYGEN@ -PBBUILD_BIN = @PBBUILD_BIN@ -SDP = @SDP@ -NSINSTALL_BIN = @NSINSTALL_BIN@ - -NSPR_CONFIG = @NSPR_CONFIG@ -NSPR_CFLAGS = @NSPR_CFLAGS@ -NSPR_LIBS = @NSPR_LIBS@ - -MOZ_NATIVE_ZLIB = @MOZ_NATIVE_ZLIB@ -MOZ_ZLIB_LIBS = @MOZ_ZLIB_LIBS@ -MOZ_ZLIB_CFLAGS = @MOZ_ZLIB_CFLAGS@ - -MOZ_NATIVE_FFI = @MOZ_NATIVE_FFI@ -MOZ_FFI_LIBS = @MOZ_FFI_LIBS@ -MOZ_FFI_CFLAGS = @MOZ_FFI_CFLAGS@ - -USE_DEPENDENT_LIBS = @USE_DEPENDENT_LIBS@ - -JS_NATIVE_EDITLINE = @JS_NATIVE_EDITLINE@ -JS_DISABLE_SHELL = @JS_DISABLE_SHELL@ -EDITLINE_LIBS = @EDITLINE_LIBS@ - -# MKSHLIB_FORCE_ALL is used to force the linker to include all object -# files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker -# to normal behavior. Makefile's that create shared libraries out of -# archives use these flags to force in all of the .o files in the -# archives into the shared library. -WRAP_LDFLAGS = @WRAP_LDFLAGS@ -DSO_CFLAGS = @DSO_CFLAGS@ -DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@ -MKSHLIB = @MKSHLIB@ -MKCSHLIB = @MKCSHLIB@ -MKSHLIB_FORCE_ALL = @MKSHLIB_FORCE_ALL@ -MKSHLIB_UNFORCE_ALL = @MKSHLIB_UNFORCE_ALL@ -DSO_LDOPTS = @DSO_LDOPTS@ -DLL_SUFFIX = @DLL_SUFFIX@ - -NO_LD_ARCHIVE_FLAGS = @NO_LD_ARCHIVE_FLAGS@ - -MOZ_NATIVE_MAKEDEPEND = @MOZ_NATIVE_MAKEDEPEND@ - -CL_INCLUDES_PREFIX = @CL_INCLUDES_PREFIX@ - -MOZ_AUTO_DEPS = @MOZ_AUTO_DEPS@ -COMPILER_DEPEND = @COMPILER_DEPEND@ -MDDEPDIR := @MDDEPDIR@ -CC_WRAPPER = @CC_WRAPPER@ -CXX_WRAPPER = @CXX_WRAPPER@ - -MOZ_DEMANGLE_SYMBOLS = @MOZ_DEMANGLE_SYMBOLS@ - -OS_TARGET=@OS_TARGET@ -OS_ARCH=@OS_ARCH@ -OS_RELEASE=@OS_RELEASE@ -OS_TEST=@OS_TEST@ -CPU_ARCH=@CPU_ARCH@ -INTEL_ARCHITECTURE=@INTEL_ARCHITECTURE@ - -# For Solaris build -SOLARIS_SUNPRO_CC = @SOLARIS_SUNPRO_CC@ -SOLARIS_SUNPRO_CXX = @SOLARIS_SUNPRO_CXX@ - -# For AIX build -AIX_OBJMODEL = @AIX_OBJMODEL@ - -# For OS/2 build -MOZ_OS2_TOOLS = @MOZ_OS2_TOOLS@ -MOZ_OS2_HIGH_MEMORY = @MOZ_OS2_HIGH_MEMORY@ - -MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@ - -# Win32 options -MOZ_BROWSE_INFO = @MOZ_BROWSE_INFO@ -MOZ_TOOLS_DIR = @MOZ_TOOLS_DIR@ -MSMANIFEST_TOOL = @MSMANIFEST_TOOL@ -MOZ_GLUE_LDFLAGS = @MOZ_GLUE_LDFLAGS@ -MOZ_GLUE_PROGRAM_LDFLAGS = @MOZ_GLUE_PROGRAM_LDFLAGS@ - -# Codesighs tools option, enables win32 mapfiles. -MOZ_MAPINFO = @MOZ_MAPINFO@ - -QEMU_CANT_RUN_JS_SHELL = @QEMU_CANT_RUN_JS_SHELL@ - -MACOS_SDK_DIR = @MACOS_SDK_DIR@ -NEXT_ROOT = @NEXT_ROOT@ -GCC_VERSION = @GCC_VERSION@ -UNIVERSAL_BINARY= @UNIVERSAL_BINARY@ -MOZ_CAN_RUN_PROGRAMS = @MOZ_CAN_RUN_PROGRAMS@ -HAVE_DTRACE= @HAVE_DTRACE@ - -VISIBILITY_FLAGS = @VISIBILITY_FLAGS@ -WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@ - -ENABLE_ION = @ENABLE_ION@ -ENABLE_METHODJIT = @ENABLE_METHODJIT@ -ENABLE_METHODJIT_SPEW = @ENABLE_METHODJIT_SPEW@ -HAVE_ARM_SIMD= @HAVE_ARM_SIMD@ - -JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@ -HAVE_LINUX_PERF_EVENT_H = @HAVE_LINUX_PERF_EVENT_H@ - -MOZ_METRO = @MOZ_METRO@ - -MOZ_ASAN = @MOZ_ASAN@ - +@ALLSUBSTS@ include $(topsrcdir)/config/baseconfig.mk diff --git a/js/src/config/makefiles/autotargets.mk b/js/src/config/makefiles/autotargets.mk index 5d6daa5fd943..794d95bcf0a8 100644 --- a/js/src/config/makefiles/autotargets.mk +++ b/js/src/config/makefiles/autotargets.mk @@ -57,14 +57,17 @@ mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done)) %/.mkdir.done: # mkdir -p -p => mkdir -p $(subst $(space)-p,$(null),$(MKDIR)) -p $(dir $@) - @$(TOUCH) $@ +# Make the timestamp old enough for not being a problem with symbolic links +# targets depending on it. Use Jan 3, 1970 to accomodate any timezone where +# 197001010000 would translate to something older than epoch. + @touch -t 197001030000 $@ # A handful of makefiles are attempting "mkdir dot". Likely not intended # or stale logic so add a stub target to handle the request and warn for now. .mkdir.done: ifndef NOWARN_AUTOTARGETS # { @echo "WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)" - @$(TOUCH) $@ + @touch -t 197001030000 $@ endif #} INCLUDED_AUTOTARGETS_MK = 1 diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 28508b7a43b0..43fc7632ffe9 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -32,7 +32,7 @@ ifdef SDK_HEADERS EXPORTS += $(SDK_HEADERS) endif -REPORT_BUILD = @echo $(notdir $<) +REPORT_BUILD = $(info $(notdir $<)) ifeq ($(OS_ARCH),OS2) EXEC = @@ -45,12 +45,18 @@ ifdef SYSTEM_LIBXUL SKIP_COPY_XULRUNNER=1 endif -# ELOG prints out failed command when building silently (gmake -s). +# ELOG prints out failed command when building silently (gmake -s). Pymake +# prints out failed commands anyway, so ELOG just makes things worse by +# forcing shell invocations. +ifndef .PYMAKE ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS)))) ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh else ELOG := -endif +endif # -s +else + ELOG := +endif # ifndef .PYMAKE _VPATH_SRCS = $(abspath $<) @@ -101,7 +107,7 @@ ifdef CPP_UNIT_TESTS CPPSRCS += $(CPP_UNIT_TESTS) SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX)) INCLUDES += -I$(DIST)/include/testing -LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) +LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS) $(if $(JS_SHARED_LIBRARY),,$(MOZ_ZLIB_LIBS)) # ...and run them the usual way check:: @@ -336,8 +342,8 @@ XPIDL_GEN_DIR = _xpidlgen ifdef MOZ_UPDATE_XTERM # Its good not to have a newline at the end of the titlebar string because it # makes the make -s output easier to read. Echo -n does not work on all -# platforms, but we can trick sed into doing it. -UPDATE_TITLE = sed -e "s!Y!$(1) in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2)!" $(MOZILLA_DIR)/config/xterm.str; +# platforms, but we can trick printf into doing it. +UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2) ; endif define SUBMAKE # $(call SUBMAKE,target,directory) @@ -1226,17 +1232,9 @@ PREF_PPFLAGS = --line-endings=crlf endif ifndef NO_DIST_INSTALL -$(FINAL_TARGET)/$(PREF_DIR): - $(NSINSTALL) -D $@ - -libs:: $(FINAL_TARGET)/$(PREF_DIR) -libs:: $(PREF_JS_EXPORTS) - $(EXIT_ON_ERROR) \ - for i in $^; do \ - dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +PREF_JS_EXPORTS_PATH := $(FINAL_TARGET)/$(PREF_DIR) +PREF_JS_EXPORTS_FLAGS := $(PREF_PPFLAGS) +PP_TARGETS += PREF_JS_EXPORTS endif endif @@ -1316,6 +1314,7 @@ libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt ifndef NO_DIST_INSTALL $(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components) ifndef NO_INTERFACES_MANIFEST +libs:: $(call mkdir_deps,$(FINAL_TARGET)/components) @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt" @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest" endif @@ -1366,22 +1365,15 @@ endif endif ifdef EXTRA_PP_COMPONENTS -libs:: $(EXTRA_PP_COMPONENTS) ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(FINAL_TARGET)/components; \ - for i in $^; do \ - fname=`basename $$i`; \ - dest=$(FINAL_TARGET)/components/$${fname}; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components +PP_TARGETS += EXTRA_PP_COMPONENTS endif endif EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)) ifneq (,$(EXTRA_MANIFESTS)) -libs:: +libs:: $(call mkdir_deps,$(FINAL_TARGET)) $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))) endif @@ -1399,17 +1391,10 @@ endif endif ifdef EXTRA_PP_JS_MODULES -libs:: $(EXTRA_PP_JS_MODULES) ifndef NO_DIST_INSTALL - $(EXIT_ON_ERROR) \ - $(NSINSTALL) -D $(JS_MODULES_PATH); \ - for i in $^; do \ - dest=$(JS_MODULES_PATH)/`basename $$i`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ - done +EXTRA_PP_JS_MODULES_PATH := $(JS_MODULES_PATH) +PP_TARGETS += EXTRA_PP_JS_MODULES endif - endif ################################################################################ @@ -1480,31 +1465,15 @@ endif endif ifneq ($(DIST_FILES),) -$(DIST)/bin: - $(NSINSTALL) -D $@ - -libs:: $(DIST)/bin -libs:: $(DIST_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done +DIST_FILES_PATH := $(FINAL_TARGET) +DIST_FILES_FLAGS := $(XULAPP_DEFINES) +PP_TARGETS += DIST_FILES endif ifneq ($(DIST_CHROME_FILES),) -libs:: $(DIST_CHROME_FILES) - @$(EXIT_ON_ERROR) \ - for f in $^; do \ - dest=$(FINAL_TARGET)/chrome/`basename $$f`; \ - $(RM) -f $$dest; \ - $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ - $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ - $$f > $$dest; \ - done +DIST_CHROME_FILES_PATH := $(FINAL_TARGET)/chrome +DIST_CHROME_FILES_FLAGS := $(XULAPP_DEFINES) +PP_TARGETS += DIST_CHROME_FILES endif ifneq ($(XPI_PKGNAME),) @@ -1662,6 +1631,58 @@ TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS) endif endif +################################################################################ +# Install/copy rules +# +# The INSTALL_TARGETS variable contains a list of all install target +# categories. Each category defines a list of files, an install destination, +# and whether the files are executables or not. +# +# FOO_FILES := foo bar +# FOO_EXECUTABLES := baz +# FOO_DEST := target_path +# INSTALL_TARGETS += FOO +define install_file_template +libs:: $(2)/$(notdir $(1)) +$(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) + $(INSTALL) $(3) $$< $${@D} +endef +$(foreach category,$(INSTALL_TARGETS),\ + $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\ + $(foreach file,$($(category)_FILES),\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS1)))\ + )\ + $(foreach file,$($(category)_EXECUTABLES),\ + $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS2)))\ + )\ +) + +################################################################################ +# Preprocessing rules +# +# The PP_TARGETS variable contains a list of all preprocessing target +# categories. Each category defines a target path, and optional extra flags +# like the following: +# +# FOO_PATH := target_path +# FOO_FLAGS := -Dsome_flag +# PP_TARGETS += FOO + +# preprocess_file_template defines preprocessing rules. +# $(call preprocess_file_template, source_file, target_path, extra_flags) +define preprocess_file_template +$(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) $$(GLOBAL_DEPS) + $$(RM) $$@ + $$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(3) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@ +libs:: $(2)/$(notdir $(1)) +endef + +$(foreach category,$(PP_TARGETS),\ + $(foreach file,$($(category)),\ + $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_FLAGS)))\ + )\ + ) + ################################################################################ # Special gmake rules. ################################################################################ @@ -1761,4 +1782,3 @@ include $(topsrcdir)/config/makefiles/autotargets.mk ifneq ($(NULL),$(AUTO_DEPS)) default all libs tools export:: $(AUTO_DEPS) endif - diff --git a/js/src/configure.in b/js/src/configure.in index f01515cbb9d0..f343b7d864ac 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1625,16 +1625,6 @@ case "$target" in MOZ_FIX_LINK_PATHS='-Wl,-executable_path,$(LIBXUL_DIST)/bin' ;; -*-freebsd*) - if test `test -x /usr/bin/objformat && /usr/bin/objformat || echo elf` != "elf"; then - DLL_SUFFIX=".so.1.0" - DSO_LDOPTS="-shared" - fi - if test ! "$GNU_CC"; then - DSO_LDOPTS="-Bshareable $DSO_LDOPTS" - fi - ;; - ia64*-hpux*) DLL_SUFFIX=".so" if test ! "$GNU_CC"; then @@ -2738,11 +2728,9 @@ then *-*-freebsd*) AC_DEFINE(_REENTRANT) AC_DEFINE(_THREAD_SAFE) - dnl -pthread links in -lc_r, so don't specify it explicitly. + dnl -pthread links in -lpthread, so don't specify it explicitly. if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" - else - _PTHREAD_LDFLAGS="-lc_r" fi ;; @@ -4229,15 +4217,6 @@ if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi -MOZ_ARG_WITH_STRING(sync-build-files, -[ --with-sync-build-files=DIR - Check that files in 'config' and 'build' match - their originals in 'DIR/config' and 'DIR/build'. - This helps keep the SpiderMonkey build machinery - in sync with Mozilla's, on which it is based.], -[MOZ_SYNC_BUILD_FILES=$withval ] ) -AC_SUBST(MOZ_SYNC_BUILD_FILES) - dnl ======================================================== dnl = dnl = Maintainer debug option (no --enable equivalent) diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index e5ec0c1792be..cdb0e772d940 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -21,20 +21,6 @@ using namespace js; using namespace js::frontend; -class AutoAttachToRuntime { - JSRuntime *rt; - ScriptSource *ss; - public: - AutoAttachToRuntime(JSRuntime *rt, ScriptSource *ss) - : rt(rt), ss(ss) {} - ~AutoAttachToRuntime() { - // This makes the source visible to the GC. If compilation fails, and no - // script refers to it, it will be collected. - if (ss) - ss->attachToRuntime(rt); - } -}; - static bool CheckLength(JSContext *cx, size_t length) { @@ -82,7 +68,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call ScriptSource *ss = cx->new_(); if (!ss) return NULL; - AutoAttachToRuntime attacher(cx->runtime, ss); + ScriptSourceHolder ssh(cx->runtime, ss); SourceCompressionToken sct(cx); if (!cx->hasRunOption(JSOPTION_ONLY_CNG_SOURCE) || options.compileAndGo) { if (!ss->setSourceCopy(cx, chars, length, false, &sct)) @@ -248,7 +234,7 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions ScriptSource *ss = cx->new_(); if (!ss) return NULL; - AutoAttachToRuntime attacher(cx->runtime, ss); + ScriptSourceHolder ssh(cx->runtime, ss); SourceCompressionToken sct(cx); if (!ss->setSourceCopy(cx, chars, length, true, &sct)) return NULL; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8c72d4b13ca8..8def1bf273cb 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -850,7 +850,6 @@ JSRuntime::JSRuntime() sameCompartmentWrapObjectCallback(NULL), preWrapObjectCallback(NULL), preserveWrapperCallback(NULL), - scriptSources(NULL), #ifdef DEBUG noGCOrAllocationCheck(0), #endif @@ -3987,7 +3986,7 @@ JS_DefineObject(JSContext *cx, JSObject *objArg, const char *name, JSClass *jscl if (!clasp) clasp = &ObjectClass; /* default class is Object */ - JSObject *nobj = NewObjectWithClassProto(cx, clasp, proto, obj); + RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, proto, obj)); if (!nobj) return NULL; @@ -4378,15 +4377,17 @@ JS_SetElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval *vp) JS_PUBLIC_API(JSBool) JS_SetProperty(JSContext *cx, JSObject *objArg, const char *name, jsval *vp) { + RootedObject obj(cx, objArg); JSAtom *atom = js_Atomize(cx, name, strlen(name)); - return atom && JS_SetPropertyById(cx, objArg, AtomToId(atom), vp); + return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp); } JS_PUBLIC_API(JSBool) JS_SetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp) { + RootedObject obj(cx, objArg); JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); - return atom && JS_SetPropertyById(cx, objArg, AtomToId(atom), vp); + return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 5ec465378e05..e0fe9037fd65 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3708,7 +3708,7 @@ NewArray(JSContext *cx, uint32_t length, RawObject protoArg) Rooted parent(cx, parent_); RootedObject proto(cx, protoArg); if (protoArg) - PoisonPtr(reinterpret_cast(protoArg)); + PoisonPtr(&protoArg); if (!proto && !FindProto(cx, &ArrayClass, parent, &proto)) return NULL; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index f8e16f5c9743..e1bdea4b49df 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -106,10 +106,6 @@ JSRuntime::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf, RuntimeSizes *run for (ScriptFilenameTable::Range r = scriptFilenameTable.all(); !r.empty(); r.popFront()) runtime->scriptFilenames += mallocSizeOf(r.front()); - runtime->scriptSources = 0; - for (ScriptSource *n = scriptSources; n; n = n->next) - runtime->scriptSources += n->sizeOfIncludingThis(mallocSizeOf); - runtime->compartmentObjects = 0; CallbackData data(mallocSizeOf); JS_IterateCompartments(this, &data, CompartmentCallback); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 51ff62b194ad..4810ff037a33 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -863,8 +863,6 @@ struct JSRuntime : js::RuntimeFriendFields js::ScriptFilenameTable scriptFilenameTable; - js::ScriptSource *scriptSources; - #ifdef DEBUG size_t noGCOrAllocationCheck; #endif diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index 5e59bc76356e..c3155ff9de77 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2590,7 +2590,7 @@ static JSBool date_toJSON(JSContext *cx, unsigned argc, Value *vp) { /* Step 1. */ - JSObject *obj = ToObject(cx, &vp[1]); + RootedObject obj(cx, ToObject(cx, &vp[1])); if (!obj) return false; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index e648e238d5aa..fe73555efcc7 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -922,4 +922,26 @@ EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled) rt->spsProfiler.enable(enabled); } +static void *gListBaseHandlerFamily = NULL; +static uint32_t gListBaseExpandoSlot = 0; + +JS_FRIEND_API(void) +SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot) +{ + gListBaseHandlerFamily = listBaseHandlerFamily; + gListBaseExpandoSlot = listBaseExpandoSlot; +} + +void * +GetListBaseHandlerFamily() +{ + return gListBaseHandlerFamily; +} + +uint32_t +GetListBaseExpandoSlot() +{ + return gListBaseExpandoSlot; +} + } // namespace js diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 89e301460fe8..856c6207f7ee 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -456,13 +456,6 @@ GetObjectSlot(RawObject obj, size_t slot) return reinterpret_cast(obj)->slotRef(slot); } -inline Shape * -GetObjectShape(RawObject obj) -{ - shadow::Shape *shape = reinterpret_cast(obj)->shape; - return reinterpret_cast(shape); -} - inline const jschar * GetAtomChars(JSAtom *atom) { @@ -893,6 +886,13 @@ NukeCrossCompartmentWrappers(JSContext* cx, const CompartmentFilter& targetFilter, NukeReferencesToWindow nukeReferencesToWindow); +/* Specify information about ListBase proxies in the DOM, for use by ICs. */ +JS_FRIEND_API(void) +SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot); + +void *GetListBaseHandlerFamily(); +uint32_t GetListBaseExpandoSlot(); + } /* namespace js */ #endif diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 46444aa0ec31..49914ce45373 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3682,10 +3682,8 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason gcReaso * script and calls rt->destroyScriptHook, the hook can still access the * script's filename. See bug 323267. */ - if (rt->gcIsFull) { + if (rt->gcIsFull) SweepScriptFilenames(rt); - ScriptSource::sweep(rt); - } /* * This removes compartments from rt->compartment, so we do it last to make diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 8c98d4b31836..c24f7b957da3 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -9,6 +9,7 @@ * JS math package. */ +#include "mozilla/Constants.h" #include "mozilla/FloatingPoint.h" #include @@ -44,9 +45,6 @@ using namespace js; #ifndef M_LN10 #define M_LN10 2.30258509299404568402 #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 481c72ea8f18..30d230e22cc4 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -383,7 +383,7 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp) } /* Step 1. */ - JSString *inputString = ToString(cx, args[0]); + RootedString inputString(cx, ToString(cx, args[0])); if (!inputString) return false; args[0].setString(inputString); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9285a953fcca..ad463bc7b840 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -335,6 +335,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) size_t vlength; Value *val; JSString *gsop[2]; + SkipRoot skipGsop(cx, &gsop, 2); JS_CHECK_RECURSION(cx, return JS_FALSE); diff --git a/js/src/json.cpp b/js/src/json.cpp index 01e2140aca28..7231a428f1ca 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -261,9 +261,9 @@ class KeyStringifier { }; template<> -class KeyStringifier { +class KeyStringifier { public: - static JSString *toString(JSContext *cx, jsid id) { + static JSString *toString(JSContext *cx, HandleId id) { return IdToString(cx, id); } }; @@ -274,9 +274,9 @@ class KeyStringifier { */ template static bool -PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, MutableHandleValue vp, StringifyContext *scx) +PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleValue vp, StringifyContext *scx) { - JSString *keyStr = NULL; + RootedString keyStr(cx); /* Step 2. */ if (vp.get().isObject()) { @@ -417,7 +417,7 @@ JO(JSContext *cx, HandleObject obj, StringifyContext *scx) RootedValue outputValue(cx); if (!obj->getGeneric(cx, id, &outputValue)) return false; - if (!PreprocessValue(cx, obj, id.get(), &outputValue, scx)) + if (!PreprocessValue(cx, obj, HandleId(id), &outputValue, scx)) return false; if (IsFilteredValue(outputValue)) continue; @@ -737,7 +737,7 @@ js_Stringify(JSContext *cx, MutableHandleValue vp, JSObject *replacer_, Value sp if (!scx.init()) return false; - if (!PreprocessValue(cx, wrapper, emptyId.get(), vp, &scx)) + if (!PreprocessValue(cx, wrapper, HandleId(emptyId), vp, &scx)) return false; if (IsFilteredValue(vp)) return true; @@ -747,7 +747,7 @@ js_Stringify(JSContext *cx, MutableHandleValue vp, JSObject *replacer_, Value sp /* ES5 15.12.2 Walk. */ static bool -Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, MutableHandleValue vp) +Walk(JSContext *cx, HandleObject holder, HandleId name, HandleValue reviver, MutableHandleValue vp) { JS_CHECK_RECURSION(cx, return false); @@ -830,7 +830,7 @@ Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, Mu } /* Step 3. */ - JSString *key = IdToString(cx, name); + RootedString key(cx, IdToString(cx, name)); if (!key) return false; @@ -850,7 +850,7 @@ Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, Mu } static bool -Revive(JSContext *cx, const Value &reviver, MutableHandleValue vp) +Revive(JSContext *cx, HandleValue reviver, MutableHandleValue vp) { RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass)); if (!obj) diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 130cfe6ed55f..16d8570c62dc 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -743,7 +743,7 @@ ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props) if (array.isPrimitive()) return true; - JSObject *obj = &array.toObject(); + RootedObject obj(cx, &array.toObject()); uint32_t length; if (!js_GetLengthProperty(cx, obj, &length)) return false; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index ed9b7413ab7d..f5a8dc982393 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -112,8 +112,10 @@ Bindings::lookup(JSContext *cx, PropertyName *name) const if (!lastBinding) return BindingIter::Init(this, NULL); + const Bindings *self = this; + SkipRoot skipSelf(cx, &self); Shape **_; - return BindingIter::Init(this, Shape::search(cx, lastBinding, NameToId(name), &_)); + return BindingIter::Init(self, Shape::search(cx, lastBinding, NameToId(name), &_)); } unsigned @@ -583,10 +585,9 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc JS_ASSERT(enclosingScript); ss = enclosingScript->scriptSource(); } + ScriptSourceHolder ssh(cx->runtime, ss); script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)), options, /* staticLevel = */ 0, ss, 0, 0); - if (scriptBits & (1 << OwnSource)) - ss->attachToRuntime(cx->runtime); if (!script || !JSScript::partiallyInit(cx, script, length, nsrcnotes, natoms, nobjects, nregexps, ntrynotes, nconsts, nClosedArgs, @@ -1093,7 +1094,6 @@ void SourceCompressorThread::waitOnCompression(SourceCompressionToken *userTok) { JS_ASSERT(userTok == tok); - JS_ASSERT(!tok->ss->onRuntime()); PR_Lock(lock); if (state == COMPRESSING) PR_WaitCondVar(done, PR_INTERVAL_NO_TIMEOUT); @@ -1130,11 +1130,7 @@ void JSScript::setScriptSource(JSContext *cx, ScriptSource *ss) { JS_ASSERT(ss); -#ifdef JSGC_INCREMENTAL - // During IGC, we need to barrier writing to scriptSource_. - if (cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull) - ss->mark(); -#endif + ss->incref(); scriptSource_ = ss; } @@ -1290,22 +1286,11 @@ SourceCompressionToken::abort() #endif } -void -ScriptSource::attachToRuntime(JSRuntime *rt) -{ - JS_ASSERT(!onRuntime()); - next = rt->scriptSources; - rt->scriptSources = this; - onRuntime_ = true; -} - void ScriptSource::destroy(JSRuntime *rt) { JS_ASSERT(ready()); - JS_ASSERT(onRuntime()); rt->free_(data.compressed); - onRuntime_ = marked = false; #ifdef DEBUG ready_ = false; #endif @@ -1315,31 +1300,11 @@ ScriptSource::destroy(JSRuntime *rt) size_t ScriptSource::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) { - JS_ASSERT(onRuntime()); JS_ASSERT(ready()); - // data is a union, but both members are pointers to allocated memory, so - // just using compressed will work. - return mallocSizeOf(this) + mallocSizeOf(data.compressed); -} -void -ScriptSource::sweep(JSRuntime *rt) -{ - JS_ASSERT(rt->gcIsFull); - ScriptSource *next = rt->scriptSources, **prev = &rt->scriptSources; - while (next) { - ScriptSource *cur = next; - next = cur->next; - JS_ASSERT(cur->ready()); - JS_ASSERT(cur->onRuntime()); - if (cur->marked) { - cur->marked = false; - prev = &cur->next; - } else { - *prev = next; - cur->destroy(rt); - } - } + // data is a union, but both members are pointers to allocated memory or + // NULL, so just using compressed will work. + return mallocSizeOf(this) + mallocSizeOf(data.compressed); } template @@ -1957,6 +1922,7 @@ JSScript::finalize(FreeOp *fop) destroyScriptCounts(fop); destroySourceMap(fop); destroyDebugScript(fop); + scriptSource_->decref(fop->runtime()); if (data) { JS_POISON(data, 0xdb, computedSizeOfData()); @@ -2607,13 +2573,8 @@ JSScript::markChildren(JSTracer *trc) if (enclosingScope_) MarkObject(trc, &enclosingScope_, "enclosing"); - if (IS_GC_MARKING_TRACER(trc)) { - if (filename) - MarkScriptFilename(trc->runtime, filename); - - if (trc->runtime->gcIsFull) - scriptSource_->mark(); - } + if (IS_GC_MARKING_TRACER(trc) && filename) + MarkScriptFilename(trc->runtime, filename); bindings.trace(trc); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index cfa8a5fc065a..ccc5398d8b88 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -1003,7 +1003,6 @@ struct SourceCompressionToken; struct ScriptSource { friend class SourceCompressorThread; - ScriptSource *next; private: union { // When the script source is ready, compressedLength_ != 0 implies @@ -1012,10 +1011,9 @@ struct ScriptSource jschar *source; unsigned char *compressed; } data; + uint32_t refs; uint32_t length_; uint32_t compressedLength_; - bool marked:1; - bool onRuntime_:1; bool argumentsNotIncluded_:1; #ifdef DEBUG bool ready_:1; @@ -1023,11 +1021,9 @@ struct ScriptSource public: ScriptSource() - : next(NULL), + : refs(0), length_(0), compressedLength_(0), - marked(false), - onRuntime_(false), argumentsNotIncluded_(false) #ifdef DEBUG ,ready_(true) @@ -1035,15 +1031,18 @@ struct ScriptSource { data.source = NULL; } + void incref() { refs++; } + void decref(JSRuntime *rt) { + JS_ASSERT(refs != 0); + if (--refs == 0) + destroy(rt); + } bool setSourceCopy(JSContext *cx, const jschar *src, uint32_t length, bool argumentsNotIncluded, SourceCompressionToken *tok); void setSource(const jschar *src, uint32_t length); - void attachToRuntime(JSRuntime *rt); - void mark() { marked = true; } - bool onRuntime() const { return onRuntime_; } #ifdef DEBUG bool ready() const { return ready_; } #endif @@ -1059,9 +1058,6 @@ struct ScriptSource JSFixedString *substring(JSContext *cx, uint32_t start, uint32_t stop); size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf); - // For the GC. - static void sweep(JSRuntime *rt); - // XDR handling template bool performXDR(XDRState *xdr); @@ -1071,6 +1067,23 @@ struct ScriptSource bool compressed() { return compressedLength_ != 0; } }; +class ScriptSourceHolder +{ + JSRuntime *rt; + ScriptSource *ss; + public: + ScriptSourceHolder(JSRuntime *rt, ScriptSource *ss) + : rt(rt), + ss(ss) + { + ss->incref(); + } + ~ScriptSourceHolder() + { + ss->decref(rt); + } +}; + #ifdef JS_THREADSAFE /* * Background thread to compress JS source code. This happens only while parsing diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 598de34e5e94..142febc91819 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1186,6 +1186,7 @@ str_indexOf(JSContext *cx, unsigned argc, Value *vp) uint32_t patlen = patstr->length(); const jschar *pat = patstr->chars(); + SkipRoot skipPat(cx, &pat); uint32_t start; if (args.length() > 1) { diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index d1de84f96f20..9a83cc355c54 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -693,17 +693,6 @@ GetProtoForClass(JSContext *cx, Class *clasp) * the subclasses. */ -static JSObject * -getTypedArray(JSObject *obj) -{ - MOZ_ASSERT(obj); - do { - if (obj->isTypedArray()) - return obj; - } while ((obj = obj->getProto())); - return NULL; -} - inline bool TypedArray::isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip) { @@ -725,19 +714,18 @@ js::IsDataView(JSObject* obj) } JSBool -TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, +TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id, MutableHandleObject objp, MutableHandleShape propp) { - JSObject *tarray = getTypedArray(obj); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); if (isArrayIndex(cx, tarray, id)) { - MarkNonNativePropertyFound(obj, propp); - objp.set(obj); + MarkNonNativePropertyFound(tarray, propp); + objp.set(tarray); return true; } - JSObject *proto = obj->getProto(); + JSObject *proto = tarray->getProto(); if (!proto) { objp.set(NULL); propp.set(NULL); @@ -756,19 +744,18 @@ TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyNa } JSBool -TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, +TypedArray::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index, MutableHandleObject objp, MutableHandleShape propp) { - JSObject *tarray = getTypedArray(obj); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); if (index < length(tarray)) { - MarkNonNativePropertyFound(obj, propp); - objp.set(obj); + MarkNonNativePropertyFound(tarray, propp); + objp.set(tarray); return true; } - if (JSObject *proto = obj->getProto()) + if (JSObject *proto = tarray->getProto()) return proto->lookupElement(cx, index, objp, propp); objp.set(NULL); @@ -957,17 +944,17 @@ class TypedArrayTemplate } static JSBool - obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, + obj_getElement(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index, MutableHandleValue vp) { - JSObject *tarray = getTypedArray(obj); + JS_ASSERT(tarray->isTypedArray()); if (index < length(tarray)) { copyIndexToValue(cx, tarray, index, vp); return true; } - JSObject *proto = obj->getProto(); + JSObject *proto = tarray->getProto(); if (!proto) { vp.setUndefined(); return true; @@ -1015,12 +1002,12 @@ class TypedArrayTemplate } static JSBool - obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, + obj_getElementIfPresent(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index, MutableHandleValue vp, bool *present) { - // Fast-path the common case of index < length - JSObject *tarray = getTypedArray(obj); + JS_ASSERT(tarray->isTypedArray()); + // Fast-path the common case of index < length if (index < length(tarray)) { // this inline function is specialized for each type copyIndexToValue(cx, tarray, index, vp); @@ -1028,7 +1015,7 @@ class TypedArrayTemplate return true; } - JSObject *proto = obj->getProto(); + JSObject *proto = tarray->getProto(); if (!proto) { vp.setUndefined(); return true; @@ -1103,11 +1090,10 @@ class TypedArrayTemplate } static JSBool - obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, + obj_setGeneric(JSContext *cx, HandleObject tarray, HandleId id, MutableHandleValue vp, JSBool strict) { - RootedObject tarray(cx, getTypedArray(obj)); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); uint32_t index; // We can't just chain to js_SetPropertyHelper, because we're not a normal object. @@ -1133,11 +1119,10 @@ class TypedArrayTemplate } static JSBool - obj_setElement(JSContext *cx, HandleObject obj, uint32_t index, + obj_setElement(JSContext *cx, HandleObject tarray, uint32_t index, MutableHandleValue vp, JSBool strict) { - RootedObject tarray(cx, getTypedArray(obj)); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); if (index >= length(tarray)) { // Silent ignore is better than an exception here, because @@ -1201,11 +1186,10 @@ class TypedArrayTemplate } static JSBool - obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, + obj_deleteElement(JSContext *cx, HandleObject tarray, uint32_t index, MutableHandleValue rval, JSBool strict) { - JSObject *tarray = getTypedArray(obj); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); if (index < length(tarray)) { rval.setBoolean(false); @@ -1217,7 +1201,7 @@ class TypedArrayTemplate } static JSBool - obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, + obj_deleteSpecial(JSContext *cx, HandleObject tarray, HandleSpecialId sid, MutableHandleValue rval, JSBool strict) { rval.setBoolean(true); @@ -1225,11 +1209,10 @@ class TypedArrayTemplate } static JSBool - obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op, + obj_enumerate(JSContext *cx, HandleObject tarray, JSIterateOp enum_op, Value *statep, jsid *idp) { - JSObject *tarray = getTypedArray(obj); - JS_ASSERT(tarray); + JS_ASSERT(tarray->isTypedArray()); uint32_t index; switch (enum_op) { @@ -1475,10 +1458,7 @@ class TypedArrayTemplate fun_subarray_impl(JSContext *cx, CallArgs args) { JS_ASSERT(IsThisClass(args.thisv())); - - JSObject *tarray = getTypedArray(&args.thisv().toObject()); - if (!tarray) - return true; + RootedObject tarray(cx, &args.thisv().toObject()); // these are the default values uint32_t begin = 0, end = length(tarray); @@ -1516,6 +1496,7 @@ class TypedArrayTemplate fun_move_impl(JSContext *cx, CallArgs args) { JS_ASSERT(IsThisClass(args.thisv())); + RootedObject tarray(cx, &args.thisv().toObject()); if (args.length() < 3) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); @@ -1526,7 +1507,6 @@ class TypedArrayTemplate uint32_t srcEnd; uint32_t dest; - JSObject *tarray = getTypedArray(&args.thisv().toObject()); uint32_t length = TypedArray::length(tarray); if (!ToClampedIndex(cx, args[0], length, &srcBegin) || !ToClampedIndex(cx, args[1], length, &srcEnd) || @@ -1579,11 +1559,7 @@ class TypedArrayTemplate fun_set_impl(JSContext *cx, CallArgs args) { JS_ASSERT(IsThisClass(args.thisv())); - - Rooted thisObj(cx, &args.thisv().toObject()); - RootedObject tarray(cx, getTypedArray(thisObj)); - if (!tarray) - return true; + RootedObject tarray(cx, &args.thisv().toObject()); // first arg must be either a typed array or a JS array if (args.length() == 0 || !args[0].isObject()) { @@ -1609,19 +1585,17 @@ class TypedArrayTemplate } RootedObject arg0(cx, args[0].toObjectOrNull()); - RootedObject src(cx, getTypedArray(arg0)); - if (src) { - if (length(src) > length(tarray) - offset) { + if (arg0->isTypedArray()) { + if (length(arg0) > length(tarray) - offset) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH); return false; } - if (!copyFromTypedArray(cx, thisObj, src, offset)) + if (!copyFromTypedArray(cx, tarray, arg0, offset)) return false; } else { - src = arg0; uint32_t len; - if (!js_GetLengthProperty(cx, src, &len)) + if (!js_GetLengthProperty(cx, arg0, &len)) return false; // avoid overflow; we know that offset <= length @@ -1630,7 +1604,7 @@ class TypedArrayTemplate return false; } - if (!copyFromArray(cx, thisObj, src, len, offset)) + if (!copyFromArray(cx, tarray, arg0, len, offset)) return false; } @@ -1787,7 +1761,7 @@ class TypedArrayTemplate MutableHandleValue vp); static JSObject * - createSubarray(JSContext *cx, JSObject *tarray, uint32_t begin, uint32_t end) + createSubarray(JSContext *cx, HandleObject tarray, uint32_t begin, uint32_t end) { JS_ASSERT(tarray); @@ -1835,8 +1809,9 @@ class TypedArrayTemplate * are treated identically. */ if (v.isPrimitive() && !v.isMagic() && !v.isUndefined()) { + RootedValue primitive(cx, v); double dval; - JS_ALWAYS_TRUE(ToNumber(cx, v, &dval)); + JS_ALWAYS_TRUE(ToNumber(cx, primitive, &dval)); return nativeFromDouble(dval); } @@ -1849,9 +1824,7 @@ class TypedArrayTemplate copyFromArray(JSContext *cx, JSObject *thisTypedArrayObj, HandleObject ar, uint32_t len, uint32_t offset = 0) { - thisTypedArrayObj = getTypedArray(thisTypedArrayObj); - JS_ASSERT(thisTypedArrayObj); - + JS_ASSERT(thisTypedArrayObj->isTypedArray()); JS_ASSERT(offset <= length(thisTypedArrayObj)); JS_ASSERT(len <= length(thisTypedArrayObj) - offset); NativeType *dest = static_cast(viewData(thisTypedArrayObj)) + offset; @@ -1861,6 +1834,7 @@ class TypedArrayTemplate JS_ASSERT(ar->getArrayLength() == len); const Value *src = ar->getDenseArrayElements(); + SkipRoot skipSrc(cx, &src); /* * It is valid to skip the hole check here because nativeFromValue @@ -1884,9 +1858,7 @@ class TypedArrayTemplate static bool copyFromTypedArray(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *tarray, uint32_t offset) { - thisTypedArrayObj = getTypedArray(thisTypedArrayObj); - JS_ASSERT(thisTypedArrayObj); - + JS_ASSERT(thisTypedArrayObj->isTypedArray()); JS_ASSERT(offset <= length(thisTypedArrayObj)); JS_ASSERT(length(tarray) <= length(thisTypedArrayObj) - offset); if (buffer(tarray) == buffer(thisTypedArrayObj)) @@ -2447,6 +2419,7 @@ DataViewObject::write(JSContext *cx, Handle obj, } uint8_t *data; + SkipRoot skipData(cx, &data); if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data)) return false; diff --git a/js/src/jstypedarrayinlines.h b/js/src/jstypedarrayinlines.h index 90dbb1498b4c..84b6fd4f66db 100644 --- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -159,11 +159,12 @@ DataViewObject::is(const Value &v) inline DataViewObject * DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength, - Handle arrayBuffer, JSObject *proto) + Handle arrayBuffer, JSObject *protoArg) { JS_ASSERT(byteOffset <= INT32_MAX); JS_ASSERT(byteLength <= INT32_MAX); + RootedObject proto(cx, protoArg); RootedObject obj(cx, NewBuiltinClassInstance(cx, &DataViewClass)); if (!obj) return NULL; diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index c5f44966eb19..faae0df6be99 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -581,10 +581,14 @@ CrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool } bool -CrossCompartmentWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) +CrossCompartmentWrapper::get(JSContext *cx, JSObject *wrapperArg, JSObject *receiverArg, + jsid idArg, Value *vp) { + RootedObject wrapper(cx, wrapperArg); + RootedObject receiver(cx, receiverArg); + RootedId id(cx, idArg); PIERCE(cx, wrapper, GET, - call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id), + call.destination->wrap(cx, receiver.address()) && call.destination->wrapId(cx, id.address()), DirectWrapper::get(cx, wrapper, receiver, id, vp), cx->compartment->wrap(cx, vp)); } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 7c3e4572d93e..a07a97da9277 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -5090,7 +5090,7 @@ mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType, */ pic.canCallHook = pic.forcedTypeBarrier = !forPrototype && - JSOp(*PC) == JSOP_GETPROP && + (JSOp(*PC) == JSOP_GETPROP || JSOp(*PC) == JSOP_LENGTH) && analysis->getCode(PC).accessGetter; /* Guard that the type is an object. */ diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index 942c6cee3510..9d764a5f0e88 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -432,6 +432,10 @@ class NunboxAssembler : public JSC::MacroAssembler return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_STRING)); } + Jump testPrivate(Condition cond, Address address, void *ptr) { + return branchPtr(cond, address, ImmPtr(ptr)); + } + void compareValue(Address one, Address two, RegisterID T0, RegisterID T1, Vector *mismatches) { loadValueAsComponents(one, T0, T1); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index c2e56a232c1f..2e02a1ce9ac2 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -597,6 +597,23 @@ IsCacheableProtoChain(JSObject *obj, JSObject *holder) return true; } +static bool +IsCacheableListBase(JSObject *obj) +{ + if (!obj->isProxy()) + return false; + + BaseProxyHandler *handler = GetProxyHandler(obj); + + if (handler->family() != GetListBaseHandlerFamily()) + return false; + + if (obj->numFixedSlots() <= GetListBaseExpandoSlot()) + return false; + + return true; +} + template struct GetPropHelper { // These fields are set in the constructor and describe a property lookup. @@ -643,6 +660,9 @@ struct GetPropHelper { JSObject *aobj = obj; if (obj->isDenseArray()) aobj = obj->getProto(); + else if (IsCacheableListBase(obj)) + aobj = obj->getProto(); + if (!aobj->isNative()) return ic.disable(f, "non-native"); @@ -1241,6 +1261,53 @@ class GetPropCompiler : public PICStubCompiler if (!shapeMismatches.append(shapeGuardJump)) return error(); + // Guard on the proxy guts for ListBase accesses, if applicable. + if (IsCacheableListBase(obj)) { + // The shape check above ensures this is a proxy with the correct + // number of fixed slots, but we need further checks to ensure that + // + // (a) the object is a ListBase. + // (b) the object does not have any expando properties, or has an + // expando which does not have the desired property. + // + // If both of these hold, all accesses on non-indexed PropertyName + // properties will go through the object's native prototype chain. + + Address handler(pic.objReg, JSObject::getFixedSlotOffset(JSSLOT_PROXY_HANDLER)); + Jump handlerGuard = masm.testPrivate(Assembler::NotEqual, handler, GetProxyHandler(obj)); + if (!shapeMismatches.append(handlerGuard)) + return error(); + + Address expandoAddress(pic.objReg, JSObject::getFixedSlotOffset(GetListBaseExpandoSlot())); + + Value expandoValue = obj->getFixedSlot(GetListBaseExpandoSlot()); + JSObject *expando = expandoValue.isObject() ? &expandoValue.toObject() : NULL; + + // Expando objects just hold any extra properties the object has + // been given by a script, and have no prototype or anything else + // that will complicate property lookups on them. + JS_ASSERT_IF(expando, expando->isNative() && expando->getProto() == NULL); + + if (expando && expando->nativeLookupNoAllocation(name) == NULL) { + Jump expandoGuard = masm.testObject(Assembler::NotEqual, expandoAddress); + if (!shapeMismatches.append(expandoGuard)) + return error(); + + masm.loadPayload(expandoAddress, pic.shapeReg); + pic.shapeRegHasBaseShape = false; + + Jump shapeGuard = masm.branchPtr(Assembler::NotEqual, + Address(pic.shapeReg, JSObject::offsetOfShape()), + ImmPtr(expando->lastProperty())); + if (!shapeMismatches.append(expandoGuard)) + return error(); + } else { + Jump expandoGuard = masm.testUndefined(Assembler::NotEqual, expandoAddress); + if (!shapeMismatches.append(expandoGuard)) + return error(); + } + } + RegisterID holderReg = pic.objReg; if (obj != holder) { if (!GeneratePrototypeGuards(cx, shapeMismatches, masm, obj, holder, @@ -2192,6 +2259,10 @@ GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandleP JS_ASSERT(v.isString()); JSContext *cx = f.cx; + // don't handle special logic required for property access on proxies. + if (!obj->isNative()) + return Lookup_Uncacheable; + GetPropHelper getprop(cx, obj, name, *this, f); LookupStatus status = getprop.lookupAndTest(); if (status != Lookup_Cacheable) diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index 5bdc29dcebe7..9d1578966830 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -349,6 +349,11 @@ class PunboxAssembler : public JSC::MacroAssembler return testString(cond, Registers::ValueReg); } + Jump testPrivate(Condition cond, Address address, void *ptr) { + uint64_t valueBits = PrivateValue(ptr).asRawBits(); + return branchPtr(cond, address, ImmPtr((void *) valueBits)); + } + void compareValue(Address one, Address two, RegisterID T0, RegisterID T1, Vector *mismatches) { loadValue(one, T0); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index bf44efc57e0f..211514a3754d 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -243,6 +243,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx) cx->free_(source); return NULL; } + ScriptSourceHolder ssh(cx->runtime, ss); ss->setSource(source, sourceLen); CompileOptions options(cx); @@ -256,7 +257,6 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx) ss, 0, ss->length())); - ss->attachToRuntime(cx->runtime); if (!script || !JSScript::fullyInitTrivial(cx, script)) return NULL; diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 4d024f560353..c8477a7ae004 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -16,6 +16,9 @@ #ifdef ANDROID #include #endif +#ifdef XP_WIN +#include +#endif #include "nsCOMPtr.h" #include "nsAutoPtr.h" @@ -180,6 +183,11 @@ Dump(JSContext *cx, unsigned argc, jsval *vp) NS_ConvertUTF16toUTF8 utf8str(reinterpret_cast(chars)); #ifdef ANDROID __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", utf8str.get()); +#endif +#ifdef XP_WIN + if (IsDebuggerPresent()) { + OutputDebugStringW(reinterpret_cast(chars)); + } #endif fputs(utf8str.get(), stdout); fflush(stdout); diff --git a/js/xpconnect/src/dictionary_helper_gen.py b/js/xpconnect/src/dictionary_helper_gen.py index a8798d96942c..6299495f7540 100644 --- a/js/xpconnect/src/dictionary_helper_gen.py +++ b/js/xpconnect/src/dictionary_helper_gen.py @@ -110,6 +110,7 @@ def print_header_file(fd, conf): "#define _gen_mozilla_idl_dictionary_helpers_h_\n\n") fd.write("#include \"jsapi.h\"\n" + "#include \"nsDOMError.h\"\n" "#include \"nsString.h\"\n" "#include \"nsCOMPtr.h\"\n\n") diff --git a/js/xpconnect/src/dombindings.cpp b/js/xpconnect/src/dombindings.cpp index 880f7a6e4869..0f3576280c3d 100644 --- a/js/xpconnect/src/dombindings.cpp +++ b/js/xpconnect/src/dombindings.cpp @@ -29,8 +29,7 @@ namespace dom { namespace binding { enum { - JSPROXYSLOT_PROTOSHAPE = 0, - JSPROXYSLOT_EXPANDO = 1 + JSPROXYSLOT_EXPANDO = 0 }; static jsid s_prototype_id = JSID_VOID; @@ -68,6 +67,12 @@ DefineStaticJSVals(JSContext *cx) int HandlerFamily; +struct SetListBaseInformation +{ + SetListBaseInformation() { + js::SetListBaseInformation((void*) &HandlerFamily, js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO); + } +} gSetListBaseInformation; JSBool Throw(JSContext *cx, nsresult rv) @@ -138,26 +143,6 @@ Unwrap(JSContext *cx, jsval v, NoType **ppArg, nsISupports **ppArgRef, jsval *vp return false; } - -// Because we use proxies for wrapping DOM list objects we don't get the benefits of the property -// cache. To improve performance when using a property that lives on the prototype chain we -// implemented a cheap caching mechanism. Every DOM list proxy object stores a pointer to a shape -// in an extra slot. The first time we access a property on the object that lives on the prototype -// we check if all the DOM properties on the prototype chain are the real DOM properties and in -// that case we store a pointer to the shape of the object's prototype in the extra slot. From -// then on, every time we access a DOM property that lives on the prototype we check that the -// shape of the prototype is still identical to the cached shape and we do a fast lookup of the -// property. If the shape has changed, we recheck all the DOM properties on the prototype chain -// and we update the shape pointer if they are still the real DOM properties. This mechanism -// covers addition/removal of properties, changes in getters/setters, changes in the prototype -// chain, ... It does not cover changes in the values of the properties. For those we store an -// enum value in a reserved slot in every DOM prototype object. The value starts off as USE_CACHE. -// If a property of a DOM prototype object is set to a different value, we set the value to -// CHECK_CACHE. The next time we try to access the value of a property on that DOM prototype -// object we check if all the DOM properties on that DOM prototype object still match the real DOM -// properties. If they do we set the value to USE_CACHE again, if they're not we set the value to -// DONT_USE_CACHE. If the value is USE_CACHE we do the fast lookup. - template typename ListBase::Properties ListBase::sProtoProperties[] = { { s_VOID_id, NULL, NULL } @@ -203,22 +188,6 @@ ListBase::getListObject(JSObject *obj) return getNative(obj); } -template -js::Shape * -ListBase::getProtoShape(JSObject *obj) -{ - JS_ASSERT(objIsList(obj)); - return (js::Shape *) js::GetProxyExtra(obj, JSPROXYSLOT_PROTOSHAPE).toPrivate(); -} - -template -void -ListBase::setProtoShape(JSObject *obj, js::Shape *shape) -{ - JS_ASSERT(objIsList(obj)); - js::SetProxyExtra(obj, JSPROXYSLOT_PROTOSHAPE, PrivateValue(shape)); -} - static JSBool UnwrapSecurityWrapper(JSContext *cx, JSObject *obj, JSObject *callee, JSObject **unwrapped) { @@ -346,43 +315,18 @@ interface_hasInstance(JSContext *cx, JSHandleObject obj, const JS::Value *vp, JS return true; } -enum { - USE_CACHE = 0, - CHECK_CACHE = 1, - DONT_USE_CACHE = 2 -}; - -static JSBool -InvalidateProtoShape_add(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp); -static JSBool -InvalidateProtoShape_set(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp); - js::Class sInterfacePrototypeClass = { "Object", - JSCLASS_HAS_RESERVED_SLOTS(1), - InvalidateProtoShape_add, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - InvalidateProtoShape_set, /* setProperty */ + JSCLASS_HAS_RESERVED_SLOTS(0), + JS_PropertyStub, /* addProperty */ + JS_PropertyStub, /* delProperty */ + JS_PropertyStub, /* getProperty */ + JS_StrictPropertyStub, /* setProperty */ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub }; -static JSBool -InvalidateProtoShape_add(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp) -{ - if (JSID_IS_STRING(id) && JS_InstanceOf(cx, obj, Jsvalify(&sInterfacePrototypeClass), NULL)) - js::SetReservedSlot(obj, 0, PrivateUint32Value(CHECK_CACHE)); - return JS_TRUE; -} - -static JSBool -InvalidateProtoShape_set(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp) -{ - return InvalidateProtoShape_add(cx, obj, id, vp); -} - template JSObject * ListBase::getPrototype(JSContext *cx, JSObject *receiver, bool *enabled) @@ -458,10 +402,6 @@ ListBase::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, NULL, 0)) return NULL; - // This needs to happen after we've set all our own properties on interfacePrototype, to - // overwrite the value set by InvalidateProtoShape_add when we set our own properties. - js::SetReservedSlot(interfacePrototype, 0, PrivateUint32Value(USE_CACHE)); - if (!cache.Put(sInterfaceClass.name, interfacePrototype, fallible_t())) return NULL; @@ -498,7 +438,6 @@ ListBase::create(JSContext *cx, JSObject *scope, ListType *aList, return NULL; NS_ADDREF(aList); - setProtoShape(obj, NULL); aWrapperCache->SetWrapper(obj); @@ -831,59 +770,6 @@ ListBase::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp) return ok; } -template -bool -ListBase::protoIsClean(JSContext *cx, JSObject *proto, bool *isClean) -{ - JSPropertyDescriptor desc; - for (size_t n = 0; n < sProtoPropertiesCount; ++n) { - jsid id = sProtoProperties[n].id; - if (!JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc)) - return false; - JSStrictPropertyOp setter = - sProtoProperties[n].setter ? sProtoProperties[n].setter : InvalidateProtoShape_set; - if (desc.obj != proto || desc.getter != sProtoProperties[n].getter || - desc.setter != setter) { - *isClean = false; - return true; - } - } - - for (size_t n = 0; n < sProtoMethodsCount; ++n) { - jsid id = sProtoMethods[n].id; - if (!JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc)) - return false; - if (desc.obj != proto || desc.getter || JSVAL_IS_PRIMITIVE(desc.value) || - n >= js::GetObjectSlotSpan(proto) || js::GetObjectSlot(proto, n + 1) != desc.value || - !JS_IsNativeFunction(JSVAL_TO_OBJECT(desc.value), sProtoMethods[n].native)) { - *isClean = false; - return true; - } - } - - *isClean = true; - return true; -} - -template -bool -ListBase::shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache) -{ - bool ok = protoIsClean(cx, proto, shouldCache); - if (!ok || !*shouldCache) - return ok; - - js::SetReservedSlot(proto, 0, PrivateUint32Value(USE_CACHE)); - - JSObject *protoProto = js::GetObjectProto(proto); - if (!protoProto) { - *shouldCache = false; - return true; - } - - return Base::shouldCacheProtoShape(cx, protoProto, shouldCache); -} - template bool ListBase::resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc) @@ -921,64 +807,6 @@ ListBase::resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPrope return Base::resolveNativeName(cx, proxy, id, desc); } -template -bool -ListBase::nativeGet(JSContext *cx, JSObject *proxy_, JSObject *proto, jsid id_, bool *found, Value *vp) -{ - JS::RootedObject proxy(cx, proxy_); - JS::RootedId id(cx, id_); - - uint32_t cache = js::GetReservedSlot(proto, 0).toPrivateUint32(); - if (cache == CHECK_CACHE) { - bool isClean; - if (!protoIsClean(cx, proto, &isClean)) - return false; - if (!isClean) { - js::SetReservedSlot(proto, 0, PrivateUint32Value(DONT_USE_CACHE)); - return true; - } - js::SetReservedSlot(proto, 0, PrivateUint32Value(USE_CACHE)); - } - else if (cache == DONT_USE_CACHE) { - return true; - } - else { -#ifdef DEBUG - bool isClean; - JS_ASSERT(protoIsClean(cx, proto, &isClean) && isClean); -#endif - } - - for (size_t n = 0; n < sProtoPropertiesCount; ++n) { - if (sProtoProperties[n].id == id) { - *found = true; - if (!vp) - return true; - - return sProtoProperties[n].getter(cx, proxy, id, JSMutableHandleValue::fromMarkedLocation(vp)); - } - } - for (size_t n = 0; n < sProtoMethodsCount; ++n) { - if (sProtoMethods[n].id == id) { - *found = true; - if (!vp) - return true; - - *vp = js::GetObjectSlot(proto, n + 1); - JS_ASSERT(JS_IsNativeFunction(&vp->toObject(), sProtoMethods[n].native)); - return true; - } - } - - JSObject *protoProto = js::GetObjectProto(proto); - if (!protoProto) { - *found = false; - return true; - } - - return Base::nativeGet(cx, proxy, protoProto, id, found, vp); -} - template bool ListBase::getPropertyOnPrototype(JSContext *cx, JSObject *proxy, jsid id, bool *found, @@ -988,33 +816,6 @@ ListBase::getPropertyOnPrototype(JSContext *cx, JSObject *proxy, jsid id, bo if (!proto) return true; - bool hit; - if (getProtoShape(proxy) != js::GetObjectShape(proto)) { - if (!shouldCacheProtoShape(cx, proto, &hit)) - return false; - if (hit) - setProtoShape(proxy, js::GetObjectShape(proto)); - } else { - hit = true; - } - - if (hit) { - if (id == s_length_id) { - if (vp) { - PRUint32 length; - getListObject(proxy)->GetLength(&length); - JS_ASSERT(int32_t(length) >= 0); - vp->setInt32(length); - } - *found = true; - return true; - } - if (!nativeGet(cx, proxy, proto, id, found, vp)) - return false; - if (*found) - return true; - } - JSBool hasProp; if (!JS_HasPropertyById(cx, proto, id, &hasProp)) return false; @@ -1038,7 +839,7 @@ ListBase::hasPropertyOnPrototype(JSContext *cx, JSObject *proxy, jsid id) } JS_ASSERT(objIsList(proxy)); - bool found; + bool found = false; // We ignore an error from getPropertyOnPrototype. return !getPropertyOnPrototype(cx, proxy, id, &found, NULL) || found; } @@ -1077,7 +878,7 @@ ListBase::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, V } } - bool found; + bool found = false; if (!getPropertyOnPrototype(cx, proxy, id, &found, vp)) return false; diff --git a/js/xpconnect/src/dombindings.h b/js/xpconnect/src/dombindings.h index 2caa15551731..c807eb14d248 100644 --- a/js/xpconnect/src/dombindings.h +++ b/js/xpconnect/src/dombindings.h @@ -78,21 +78,10 @@ class NoBase { public: static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, JSObject *receiver); - static bool shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache) - { - *shouldCache = true; - return true; - } static bool resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc) { return true; } - static bool nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id, bool *found, - JS::Value *vp) - { - *found = false; - return true; - } static nsISupports* nativeToSupports(nsISupports* aNative) { return aNative; @@ -144,9 +133,6 @@ private: static JSObject *ensureExpandoObject(JSContext *cx, JSObject *obj); - static js::Shape *getProtoShape(JSObject *obj); - static void setProtoShape(JSObject *obj, js::Shape *shape); - static JSBool length_getter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp); static inline bool getItemAt(ListType *list, uint32_t i, IndexGetterType &item); @@ -213,12 +199,8 @@ public: static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, JSObject *receiver); - static inline bool protoIsClean(JSContext *cx, JSObject *proto, bool *isClean); - static bool shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache); static bool resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc); - static bool nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id, bool *found, - JS::Value *vp); static ListType *getNative(JSObject *proxy); static nsISupports* nativeToSupports(ListType* aNative) { diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 9f163fbaa01d..24f3c2d30efb 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -742,20 +742,6 @@ xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS) } } -static bool -WrapperIsNotMainThreadOnly(XPCWrappedNative *wrapper) -{ - XPCWrappedNativeProto *proto = wrapper->GetProto(); - if (proto && proto->ClassIsMainThreadOnly()) - return false; - - // If the native participates in cycle collection then we know it can only - // be used on the main thread. In that case we assume the wrapped native - // can only be used on the main thread too. - nsXPCOMCycleCollectionParticipant* participant; - return NS_FAILED(CallQueryInterface(wrapper->Native(), &participant)); -} - static inline void DescribeGCThing(bool isMarked, void *p, JSGCTraceKind traceKind, nsCycleCollectionTraversalCallback &cb) @@ -873,53 +859,26 @@ TraverseGCThing(TraverseSelect ts, void *p, JSGCTraceKind traceKind, nsCycleCollectionTraversalCallback &cb) { MOZ_ASSERT(traceKind == js_GetGCThingTraceKind(p)); - JSObject *obj = nullptr; - js::Class *clasp = nullptr; - - // We do not want to add wrappers to the cycle collector if they're not - // explicitly marked as main thread only, because the cycle collector isn't - // able to deal with objects that might be used off of the main thread. We - // do want to explicitly mark them for cycle collection if the wrapper has - // an external reference, because the wrapper would mark the JS object if - // we did add the wrapper to the cycle collector. - bool dontTraverse = false; - bool markJSObject = false; - if (traceKind == JSTRACE_OBJECT) { - obj = static_cast(p); - clasp = js::GetObjectClass(obj); - - if (clasp == &XPC_WN_Tearoff_JSClass) { - XPCWrappedNative *wrapper = - static_cast(xpc_GetJSPrivate(js::GetObjectParent(obj))); - dontTraverse = WrapperIsNotMainThreadOnly(wrapper); - } else if (IS_WRAPPER_CLASS(clasp) && IS_WN_WRAPPER_OBJECT(obj)) { - XPCWrappedNative *wrapper = - static_cast(xpc_GetJSPrivate(obj)); - dontTraverse = WrapperIsNotMainThreadOnly(wrapper); - markJSObject = dontTraverse && wrapper->HasExternalReference(); - } - } - - bool isMarked = markJSObject || !xpc_IsGrayGCThing(p); + bool isMarkedGray = xpc_IsGrayGCThing(p); if (ts == TRAVERSE_FULL) - DescribeGCThing(isMarked, p, traceKind, cb); + DescribeGCThing(!isMarkedGray, p, traceKind, cb); // If this object is alive, then all of its children are alive. For JS objects, // the black-gray invariant ensures the children are also marked black. For C++ // objects, the ref count from this object will keep them alive. Thus we don't // need to trace our children, unless we are debugging using WantAllTraces. - if (isMarked && !cb.WantAllTraces()) + if (!isMarkedGray && !cb.WantAllTraces()) return; if (ts == TRAVERSE_FULL) NoteGCThingJSChildren(nsXPConnect::GetRuntimeInstance()->GetJSRuntime(), p, traceKind, cb); - if (traceKind != JSTRACE_OBJECT || dontTraverse) - return; - - NoteGCThingXPCOMChildren(clasp, obj, cb); + if (traceKind == JSTRACE_OBJECT) { + JSObject *obj = static_cast(p); + NoteGCThingXPCOMChildren(js::GetObjectClass(obj), obj, cb); + } } NS_METHOD diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5e77158822fd..efcfb8bdd4ef 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -326,12 +326,13 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, } static void -AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem, - nsCSSProperty aProperty) +AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, nsCSSProperty aProperty) { aLayer->ClearAnimations(); nsIFrame* frame = aItem->GetUnderlyingFrame(); + nsIContent* aContent = frame->GetContent(); ElementTransitions* et = nsTransitionManager::GetTransitionsForCompositor(aContent, aProperty); @@ -343,6 +344,23 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem, return; } + // If the frame is not prerendered, bail out. Layout will still perform the + // animation. + if (!nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, frame)) { + if (nsLayoutUtils::IsAnimationLoggingEnabled()) { + nsIContent* aContent = frame->GetContent(); + printf_stderr("Performance warning: Async animation disabled because the frame for element '%s'", + nsAtomCString(aContent->Tag()).get()); + nsIAtom* id = aContent->GetID(); + if (id) { + printf_stderr(" with id '%s'", + nsAtomCString(aContent->GetID()).get()); + } + printf_stderr(" is not prerendered\n"); + } + return; + } + mozilla::TimeStamp currentTime = frame->PresContext()->RefreshDriver()->MostRecentRefresh(); AnimationData data; @@ -2352,7 +2370,8 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder, return nullptr; container->SetOpacity(mFrame->GetStyleDisplay()->mOpacity); - AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_opacity); + AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, eCSSProperty_opacity); return container.forget(); } @@ -3364,7 +3383,8 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D); } - AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_transform); + AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, eCSSProperty_transform); return container.forget(); } diff --git a/layout/base/nsFrameIterator.cpp b/layout/base/nsFrameIterator.cpp index ff5c681e48f2..5a3d1790b3a3 100644 --- a/layout/base/nsFrameIterator.cpp +++ b/layout/base/nsFrameIterator.cpp @@ -14,9 +14,9 @@ nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart, , mOffEdge(0) , mType(aType) { - mFollowOOFs = (aFlags & FrameIteratorFlags::FLAG_FOLLOW_OUT_OF_FLOW) != 0; - mLockScroll = (aFlags & FrameIteratorFlags::FLAG_LOCK_SCROLL) != 0; - mVisual = (aFlags & FrameIteratorFlags::FLAG_VISUAL) != 0; + mFollowOOFs = (aFlags & FLAG_FOLLOW_OUT_OF_FLOW) != 0; + mLockScroll = (aFlags & FLAG_LOCK_SCROLL) != 0; + mVisual = (aFlags & FLAG_VISUAL) != 0; if (mFollowOOFs && aStart) aStart = nsPlaceholderFrame::GetRealFrameFor(aStart); setStart(aStart); diff --git a/layout/base/nsFrameIterator.h b/layout/base/nsFrameIterator.h index b2d9fb531158..21aad301419e 100644 --- a/layout/base/nsFrameIterator.h +++ b/layout/base/nsFrameIterator.h @@ -16,13 +16,6 @@ enum nsIteratorType { ePostOrder }; -enum FrameIteratorFlags { - FLAG_NONE = 0, - FLAG_LOCK_SCROLL = 1 << 1, - FLAG_FOLLOW_OUT_OF_FLOW = 1 << 2, - FLAG_VISUAL = 1 << 3 -}; - class nsFrameIterator { public: @@ -38,6 +31,13 @@ public: void Last(); void Prev(); + + enum FrameIteratorFlags { + FLAG_NONE = 0, + FLAG_LOCK_SCROLL = 1 << 1, + FLAG_FOLLOW_OUT_OF_FLOW = 1 << 2, + FLAG_VISUAL = 1 << 3 + }; protected: void setCurrent(nsIFrame *aFrame){mCurrent = aFrame;} nsIFrame *getCurrent(){return mCurrent;} diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index e581313c4ac9..e5e76f7f4f92 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -188,6 +188,21 @@ nsLayoutUtils::AreTransformAnimationsEnabled() return sAreTransformAnimationsEnabled && CompositorParent::CompositorLoop(); } +bool +nsLayoutUtils::IsAnimationLoggingEnabled() +{ + static bool sShouldLog; + static bool sShouldLogPrefCached; + + if (!sShouldLogPrefCached) { + sShouldLogPrefCached = true; + Preferences::AddBoolVarCache(&sShouldLog, + "layers.offmainthreadcomposition.log-animations"); + } + + return sShouldLog; +} + bool nsLayoutUtils::UseBackgroundNearestFiltering() { diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index ea8829a77b22..76caa1cd0320 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1515,6 +1515,11 @@ public: static bool AreOpacityAnimationsEnabled(); static bool AreTransformAnimationsEnabled(); + /** + * Checks if we should warn about animations that can't be async + */ + static bool IsAnimationLoggingEnabled(); + /** * Checks if we should forcibly use nearest pixel filtering for the * background. diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 67a92d3b0905..31bbe4bac17b 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -742,6 +742,7 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_UNICODE_BIDI_EMBED 0x1 #define NS_STYLE_UNICODE_BIDI_ISOLATE 0x2 #define NS_STYLE_UNICODE_BIDI_OVERRIDE 0x4 +#define NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE 0x6 #define NS_STYLE_UNICODE_BIDI_PLAINTEXT 0x8 // See nsStyleTable (here for HTML 4.0 for now, should probably change to side flags) diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index f549638e6898..68503014cc8e 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -209,7 +209,6 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder, bool snap; nsRect bounds = GetBounds(aBuilder, &snap); - nsIntRect pixelRect = bounds.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel()); nsRenderingContext context; nsRefPtr dest = aCtx->ThebesContext(); nsRefPtr surf; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 5c4826c58670..04718f42b5b0 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5782,9 +5782,9 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, //resultFrame is not a block frame result = NS_ERROR_FAILURE; - PRUint32 flags = FrameIteratorFlags::FLAG_NONE; + PRUint32 flags = nsFrameIterator::FLAG_NONE; if (aPos->mScrollViewStop) { - flags |= FrameIteratorFlags::FLAG_LOCK_SCROLL; + flags |= nsFrameIterator::FLAG_LOCK_SCROLL; } nsFrameIterator frameTraversal(aPresContext, resultFrame, ePostOrder, flags); @@ -5873,9 +5873,9 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, if (!found){ resultFrame = storeOldResultFrame; - PRUint32 flags = FrameIteratorFlags::FLAG_NONE; + PRUint32 flags = nsFrameIterator::FLAG_NONE; if (aPos->mScrollViewStop) { - flags |= FrameIteratorFlags::FLAG_LOCK_SCROLL; + flags |= nsFrameIterator::FLAG_LOCK_SCROLL; } frameTraversal = nsFrameIterator(aPresContext, resultFrame, eLeaf, flags); @@ -6634,12 +6634,12 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual, return NS_ERROR_FAILURE; //we are done. cannot jump lines } - PRUint32 flags = FrameIteratorFlags::FLAG_FOLLOW_OUT_OF_FLOW; + PRUint32 flags = nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW; if (aScrollViewStop) { - flags |= FrameIteratorFlags::FLAG_LOCK_SCROLL; + flags |= nsFrameIterator::FLAG_LOCK_SCROLL; } if (aVisual && presContext->BidiEnabled()) { - flags |= FrameIteratorFlags::FLAG_VISUAL; + flags |= nsFrameIterator::FLAG_VISUAL; } nsFrameIterator frameTraversal(presContext, traversedFrame, eLeaf, flags); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 547e3d514f77..e77b4efe0258 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -54,6 +54,7 @@ #include "nsSVGOuterSVGFrame.h" #include "mozilla/Attributes.h" #include "ScrollbarActivity.h" +#include "nsRefreshDriver.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 21e68e9a34c7..7e248c635c12 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1228,7 +1228,7 @@ nsFrameSelection::GetFrameFromLevel(nsIFrame *aFrameIn, nsIFrame *foundFrame = aFrameIn; nsFrameIterator frameTraversal(mShell->GetPresContext(), aFrameIn, - eLeaf, FrameIteratorFlags::FLAG_NONE); + eLeaf, nsFrameIterator::FLAG_NONE); do { *aFrameOut = foundFrame; diff --git a/layout/media/Makefile.in b/layout/media/Makefile.in index bab647cde9ce..8e68d733f2a6 100644 --- a/layout/media/Makefile.in +++ b/layout/media/Makefile.in @@ -131,6 +131,12 @@ EXTRA_DSO_LDOPTS += \ -LIBPATH:"$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)" \ $(NULL) OS_LIBS += $(call EXPAND_LIBNAME,secur32 crypt32 iphlpapi strmiids dmoguids wmcodecdspuuid amstrmid msdmo wininet) +ifdef _MSC_VER +OS_LIBS += $(call EXPAND_LIBNAME,delayimp) +EXTRA_DSO_LDOPTS += \ + -DELAYLOAD:msdmo.dll \ + $(NULL) +endif endif DEFFILE = symbols.def diff --git a/layout/reftests/bidi/613149-1b.html b/layout/reftests/bidi/613149-1b.html index b639b0d5d4d6..67f259eb8499 100644 --- a/layout/reftests/bidi/613149-1b.html +++ b/layout/reftests/bidi/613149-1b.html @@ -6,7 +6,7 @@ diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 67d53f24bc69..ec2d49dabd63 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -220,22 +220,14 @@ bool CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *aElement, nsCSSProperty aProperty) { - static bool sShouldLog; - static bool sShouldLogPrefCached; - - if (!sShouldLogPrefCached) { - sShouldLogPrefCached = true; - Preferences::AddBoolVarCache(&sShouldLog, - "layers.offmainthreadcomposition.log-animations"); - } - + bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled(); nsIFrame* frame = aElement->GetPrimaryFrame(); if (aProperty == eCSSProperty_visibility) { return true; } if (aProperty == eCSSProperty_opacity) { bool enabled = nsLayoutUtils::AreOpacityAnimationsEnabled(); - if (!enabled && sShouldLog) { + if (!enabled && shouldLog) { printf_stderr("Performance warning: Async animation of 'opacity' is disabled\n"); } return enabled; @@ -244,24 +236,24 @@ CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *a if (frame && frame->Preserves3D() && frame->Preserves3DChildren()) { - if (sShouldLog) { + if (shouldLog) { printf_stderr("Gecko bug: Async animation of 'preserve-3d' transforms is not supported. See bug 779598\n"); } return false; } if (frame && frame->IsSVGTransformed()) { - if (sShouldLog) { + if (shouldLog) { printf_stderr("Gecko bug: Async 'transform' animations of frames with SVG transforms is not supported. See bug 779599\n"); } return false; } bool enabled = nsLayoutUtils::AreTransformAnimationsEnabled(); - if (!enabled && sShouldLog) { + if (!enabled && shouldLog) { printf_stderr("Performance warning: Async animation of 'transform' is disabled\n"); } return enabled; } - if (sShouldLog) { + if (shouldLog) { const nsAFlatCString propName = nsCSSProps::GetStringValue(aProperty); printf_stderr("Performance warning: Async animation cancelled because of unsupported property '%s'\n", propName.get()); } diff --git a/layout/style/html.css b/layout/style/html.css index ee9e58a797a2..42bd05def8a3 100644 --- a/layout/style/html.css +++ b/layout/style/html.css @@ -88,7 +88,7 @@ bdo, bdo[dir] { unicode-bidi: bidi-override; } bdo[dir="auto"] { - unicode-bidi: bidi-override -moz-isolate; + unicode-bidi: -moz-isolate-override; } textarea[dir="auto"], pre[dir="auto"] { unicode-bidi: -moz-plaintext; } diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index f87c366dc8c9..d9b9df3d6a29 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -101,6 +101,7 @@ CSS_KEY(-moz-inline-flex, _moz_inline_flex) CSS_KEY(-moz-inline-grid, _moz_inline_grid) CSS_KEY(-moz-inline-stack, _moz_inline_stack) CSS_KEY(-moz-isolate, _moz_isolate) +CSS_KEY(-moz-isolate-override, _moz_isolate_override) CSS_KEY(-moz-japanese-formal, _moz_japanese_formal) CSS_KEY(-moz-japanese-informal, _moz_japanese_informal) CSS_KEY(-moz-kannada, _moz_kannada) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index e15ecbc3f515..7d3f5a28a8e4 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -519,7 +519,6 @@ protected: bool ParseTextDecoration(); bool ParseTextDecorationLine(nsCSSValue& aValue); bool ParseTextOverflow(nsCSSValue& aValue); - bool ParseUnicodeBidi(nsCSSValue& aValue); bool ParseShadowItem(nsCSSValue& aValue, bool aIsBoxShadow); bool ParseShadowList(nsCSSProperty aProperty); @@ -6171,8 +6170,6 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue, return ParseTextDecorationLine(aValue); case eCSSProperty_text_overflow: return ParseTextOverflow(aValue); - case eCSSProperty_unicode_bidi: - return ParseUnicodeBidi(aValue); default: NS_ABORT_IF_FALSE(false, "should not reach here"); return false; @@ -9291,33 +9288,6 @@ CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue) } return true; } - -bool -CSSParserImpl::ParseUnicodeBidi(nsCSSValue& aValue) -{ - if (ParseVariant(aValue, VARIANT_HK, nsCSSProps::kUnicodeBidiKTable)) { - if (eCSSUnit_Enumerated == aValue.GetUnit()) { - PRInt32 intValue = aValue.GetIntValue(); - // unicode-bidi can have either one or two values, but the only legal - // combination of two values is 'isolate bidi-override' - if (intValue == NS_STYLE_UNICODE_BIDI_ISOLATE || - intValue == NS_STYLE_UNICODE_BIDI_OVERRIDE) { - // look for more keywords - nsCSSValue second; - if (ParseEnum(second, nsCSSProps::kUnicodeBidiKTable)) { - intValue |= second.GetIntValue(); - if (intValue != (NS_STYLE_UNICODE_BIDI_ISOLATE | - NS_STYLE_UNICODE_BIDI_OVERRIDE)) { - return false; - } - } - aValue.SetIntValue(intValue, eCSSUnit_Enumerated); - } - } - return true; - } - return false; -} bool CSSParserImpl::ParseTransitionProperty() diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 851cf56203d5..4350652bf31d 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2758,10 +2758,9 @@ CSS_PROP_TEXTRESET( unicode-bidi, unicode_bidi, UnicodeBidi, - CSS_PROPERTY_PARSE_VALUE | - CSS_PROPERTY_VALUE_PARSER_FUNCTION, + CSS_PROPERTY_PARSE_VALUE, "", - 0, + VARIANT_HK, kUnicodeBidiKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_None) diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 9cc3ee150dd4..b0ea193eb87f 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -1370,6 +1370,7 @@ const PRInt32 nsCSSProps::kUnicodeBidiKTable[] = { eCSSKeyword_embed, NS_STYLE_UNICODE_BIDI_EMBED, eCSSKeyword_bidi_override, NS_STYLE_UNICODE_BIDI_OVERRIDE, eCSSKeyword__moz_isolate, NS_STYLE_UNICODE_BIDI_ISOLATE, + eCSSKeyword__moz_isolate_override, NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE, eCSSKeyword__moz_plaintext, NS_STYLE_UNICODE_BIDI_PLAINTEXT, eCSSKeyword_UNKNOWN,-1 }; diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 3dad12a6f247..915513c466a3 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -828,21 +828,6 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const aResult); } } - else if (eCSSProperty_unicode_bidi == aProperty) { - MOZ_STATIC_ASSERT(NS_STYLE_UNICODE_BIDI_NORMAL == 0, - "unicode-bidi style constants not as expected"); - PRInt32 intValue = GetIntValue(); - if (NS_STYLE_UNICODE_BIDI_NORMAL == intValue) { - AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue), - aResult); - } else { - nsStyleUtil::AppendBitmaskCSSValue( - aProperty, intValue, - NS_STYLE_UNICODE_BIDI_EMBED, - NS_STYLE_UNICODE_BIDI_PLAINTEXT, - aResult); - } - } else { const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, GetIntValue()); AppendASCIItoUTF16(name, aResult); diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 639e202dc09a..4ffef5f1dcb8 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2725,19 +2725,9 @@ nsIDOMCSSValue* nsComputedDOMStyle::DoGetUnicodeBidi() { nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue(); - PRInt32 intValue = GetStyleTextReset()->mUnicodeBidi; - - if (NS_STYLE_UNICODE_BIDI_NORMAL == intValue) { - val->SetIdent(eCSSKeyword_normal); - } else { - nsAutoString unicodeBidiString; - nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_unicode_bidi, intValue, - NS_STYLE_UNICODE_BIDI_EMBED, - NS_STYLE_UNICODE_BIDI_PLAINTEXT, - unicodeBidiString); - val->SetString(unicodeBidiString); - } - + val->SetIdent( + nsCSSProps::ValueToKeywordEnum(GetStyleTextReset()->mUnicodeBidi, + nsCSSProps::kUnicodeBidiKTable)); return val; } diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index 639a425a6373..052bc984e6a2 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -13,6 +13,7 @@ #include "nsFontFaceLoader.h" +#include "nsDOMError.h" #include "nsError.h" #include "nsIFile.h" #include "nsIStreamListener.h" diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 1650a78ba898..b328d4d3bd18 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -3387,8 +3387,8 @@ var gCSSProperties = { inherited: false, type: CSS_TYPE_LONGHAND, initial_values: [ "normal" ], - other_values: [ "embed", "bidi-override", "-moz-isolate", "-moz-plaintext", "-moz-isolate bidi-override", "bidi-override -moz-isolate" ], - invalid_values: [ "auto", "none", "normal embed", "normal bidi-override", "normal -moz-isolate", "normal -moz-plaintext", "embed normal", "embed -moz-isolate", "embed bidi-override", "embed -moz-plaintext", "bidi-override normal", "bidi-override embed", "bidi-override -moz-plaintext", "-moz-isolate normal", "-moz-isolate embed", "-moz-isolate -moz-plaintext", "-moz-plaintext normal", "-moz-plaintext embed", "-moz-plaintext bidi-override", "-moz-plaintext -moz-isolate" ] + other_values: [ "embed", "bidi-override", "-moz-isolate", "-moz-plaintext", "-moz-isolate-override" ], + invalid_values: [ "auto", "none" ] }, "vertical-align": { domProp: "verticalAlign", diff --git a/layout/style/test/test_default_bidi_css.html b/layout/style/test/test_default_bidi_css.html index 7ffcbb6fb35e..3386a075ea56 100644 --- a/layout/style/test/test_default_bidi_css.html +++ b/layout/style/test/test_default_bidi_css.html @@ -52,7 +52,7 @@ var tests = [ ['bdo', {}, 'ltr', 'bidi-override'], ['bdo', {'dir': 'ltr'}, 'ltr', 'bidi-override'], ['bdo', {'dir': 'rtl'}, 'rtl', 'bidi-override'], - ['bdo', {'dir': 'auto'}, 'ltr', '-moz-isolate bidi-override'], + ['bdo', {'dir': 'auto'}, 'ltr', '-moz-isolate-override'], ['bdo', {'dir': ''}, 'ltr', 'bidi-override'], ['textarea', {}, 'ltr', 'normal'], diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h index c94aaa949d10..aeee5abe03fb 100644 --- a/layout/svg/base/src/nsSVGUtils.h +++ b/layout/svg/base/src/nsSVGUtils.h @@ -22,6 +22,7 @@ #include "nsMathUtils.h" #include "nsPoint.h" #include "nsRect.h" +#include "mozilla/Constants.h" class gfxASurface; class gfxContext; @@ -56,10 +57,6 @@ class Element; } // namespace dom } // namespace mozilla -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - // SVG Frame state bits #define NS_STATE_IS_OUTER_SVG NS_FRAME_STATE_BIT(20) diff --git a/layout/xul/base/src/tree/src/nsTreeContentView.cpp b/layout/xul/base/src/tree/src/nsTreeContentView.cpp index 135e3a760e14..3b608006ea8d 100644 --- a/layout/xul/base/src/tree/src/nsTreeContentView.cpp +++ b/layout/xul/base/src/tree/src/nsTreeContentView.cpp @@ -10,6 +10,7 @@ #include "nsTreeContentView.h" #include "nsChildIterator.h" #include "nsDOMClassInfoID.h" +#include "nsDOMError.h" #include "nsEventStates.h" #include "nsINodeInfo.h" #include "nsIXULSortService.h" diff --git a/memory/build/extraMallocFuncs.c b/memory/build/extraMallocFuncs.c index 49111c1dc17c..9d87629b9927 100644 --- a/memory/build/extraMallocFuncs.c +++ b/memory/build/extraMallocFuncs.c @@ -5,10 +5,12 @@ #include #include "mozilla/Types.h" -#ifdef ANDROID +#ifdef MOZ_WIDGET_ANDROID #define wrap(a) __wrap_ ## a #elif defined(XP_WIN) || defined(XP_MACOSX) #define wrap(a) je_ ## a +#elif defined(MOZ_WIDGET_GONK) +#define wrap(a) a #endif #ifdef wrap diff --git a/memory/mozjemalloc/jemalloc.c b/memory/mozjemalloc/jemalloc.c index 78827ad6e606..631e736ed2e1 100644 --- a/memory/mozjemalloc/jemalloc.c +++ b/memory/mozjemalloc/jemalloc.c @@ -6218,6 +6218,7 @@ malloc_shutdown() /* * Mangle standard interfaces, in order to avoid linking problems. */ +#ifndef MOZ_MEMORY_GONK #if defined(MOZ_MEMORY_DARWIN) || defined(MOZ_MEMORY_WINDOWS) || \ defined(MOZ_MEMORY_ANDROID) @@ -6241,6 +6242,7 @@ malloc_shutdown() #define free(a) wrap(free)(a) #define malloc_usable_size(a) wrap(malloc_usable_size)(a) #endif +#endif /* * Even though we compile with MOZ_MEMORY, we may have to dynamically decide diff --git a/mfbt/Constants.h b/mfbt/Constants.h new file mode 100644 index 000000000000..904b30145a8d --- /dev/null +++ b/mfbt/Constants.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* mfbt math constants. */ + +#ifndef mozilla_Constants_h_ +#define mozilla_Constants_h_ + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#endif /* mozilla_Constants_h_ */ diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index 7f457567ed7d..faf2ff6bbfd5 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -13,6 +13,7 @@ EXPORTS_mozilla += \ Attributes.h \ BloomFilter.h \ CheckedInt.h \ + Constants.h \ FloatingPoint.h \ GuardObjects.h \ HashFunctions.h \ diff --git a/mobile/android/base/AboutHomeContent.java b/mobile/android/base/AboutHomeContent.java index c91988c8f0cd..d25b99e9bfde 100644 --- a/mobile/android/base/AboutHomeContent.java +++ b/mobile/android/base/AboutHomeContent.java @@ -335,8 +335,10 @@ public class AboutHomeContent extends ScrollView mNumberOfCols = getResources().getInteger(R.integer.number_of_top_sites_cols); } - @Override - public void onConfigurationChanged(Configuration newConfig) { + /** + * Reinflates and updates all components of this view. + */ + public void refresh() { if (mTopSitesAdapter != null) mTopSitesAdapter.notifyDataSetChanged(); @@ -344,8 +346,6 @@ public class AboutHomeContent extends ScrollView inflate(); mTopSitesGrid.setAdapter(mTopSitesAdapter); // mTopSitesGrid is a new instance (from loadTopSites()). update(AboutHomeContent.UpdateFlags.ALL); // Refresh all elements. - - super.onConfigurationChanged(newConfig); } @Override diff --git a/mobile/android/base/ActivityHandlerHelper.java b/mobile/android/base/ActivityHandlerHelper.java index 929039d2b051..c488430f9708 100644 --- a/mobile/android/base/ActivityHandlerHelper.java +++ b/mobile/android/base/ActivityHandlerHelper.java @@ -4,6 +4,9 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.ActivityResultHandler; +import org.mozilla.gecko.util.ActivityResultHandlerMap; + import org.json.JSONException; import org.json.JSONObject; diff --git a/mobile/android/base/ActivityResultHandler.java b/mobile/android/base/ActivityResultHandler.java index d312f18fac39..6f40ee96b5a1 100644 --- a/mobile/android/base/ActivityResultHandler.java +++ b/mobile/android/base/ActivityResultHandler.java @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; import android.content.Intent; -interface ActivityResultHandler { - public void onActivityResult(int resultCode, Intent data); +public interface ActivityResultHandler { + void onActivityResult(int resultCode, Intent data); } diff --git a/mobile/android/base/ActivityResultHandlerMap.java b/mobile/android/base/ActivityResultHandlerMap.java index 6896c4f96ac1..781f3b709b2d 100644 --- a/mobile/android/base/ActivityResultHandlerMap.java +++ b/mobile/android/base/ActivityResultHandlerMap.java @@ -2,21 +2,21 @@ * 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; +package org.mozilla.gecko.util; import java.util.HashMap; import java.util.Map; -class ActivityResultHandlerMap { +public final class ActivityResultHandlerMap { private Map mMap = new HashMap(); private int mCounter = 0; - synchronized int put(ActivityResultHandler handler) { + public synchronized int put(ActivityResultHandler handler) { mMap.put(mCounter, handler); return mCounter++; } - synchronized ActivityResultHandler getAndRemove(int i) { + public synchronized ActivityResultHandler getAndRemove(int i) { return mMap.remove(i); } } diff --git a/mobile/android/base/AndroidImportPreference.java b/mobile/android/base/AndroidImportPreference.java index e17c16d81d1e..907248eb20b0 100644 --- a/mobile/android/base/AndroidImportPreference.java +++ b/mobile/android/base/AndroidImportPreference.java @@ -5,6 +5,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.GeckoBackgroundThread; + import android.app.ProgressDialog; import android.content.Context; import android.util.AttributeSet; diff --git a/mobile/android/base/AwesomeBar.java b/mobile/android/base/AwesomeBar.java index c66ec6102a80..90693c924d57 100644 --- a/mobile/android/base/AwesomeBar.java +++ b/mobile/android/base/AwesomeBar.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.util.GeckoAsyncTask; import android.app.Activity; import android.app.AlertDialog; @@ -511,7 +512,7 @@ public class AwesomeBar extends GeckoActivity { editPrompt.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - (new GeckoAsyncTask() { + (new GeckoAsyncTask(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { String newUrl = locationText.getText().toString().trim(); @@ -587,7 +588,7 @@ public class AwesomeBar extends GeckoActivity { break; } case R.id.remove_history: { - (new GeckoAsyncTask() { + (new GeckoAsyncTask(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { BrowserDB.removeHistoryEntry(mResolver, id); diff --git a/mobile/android/base/AwesomebarResultHandler.java b/mobile/android/base/AwesomebarResultHandler.java index 5555309a8e4a..f1ac3923fac0 100644 --- a/mobile/android/base/AwesomebarResultHandler.java +++ b/mobile/android/base/AwesomebarResultHandler.java @@ -4,6 +4,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.ActivityResultHandler; + import android.content.Intent; class AwesomebarResultHandler implements ActivityResultHandler { diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index e301934ffba1..881da032d19b 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -287,6 +287,9 @@ abstract public class BrowserApp extends GeckoApp invalidateOptionsMenu(); mTabsPanel.refresh(); + + if (mAboutHomeContent != null) + mAboutHomeContent.refresh(); } public View getActionBarLayout() { diff --git a/mobile/android/base/CameraImageResultHandler.java b/mobile/android/base/CameraImageResultHandler.java index 5e889d4a1f04..af6c7fa17836 100644 --- a/mobile/android/base/CameraImageResultHandler.java +++ b/mobile/android/base/CameraImageResultHandler.java @@ -4,6 +4,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.ActivityResultHandler; + import android.app.Activity; import android.content.Intent; import android.os.Environment; diff --git a/mobile/android/base/CameraVideoResultHandler.java b/mobile/android/base/CameraVideoResultHandler.java index 04194206e1e5..d50478f92e29 100644 --- a/mobile/android/base/CameraVideoResultHandler.java +++ b/mobile/android/base/CameraVideoResultHandler.java @@ -4,6 +4,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.ActivityResultHandler; + import android.app.Activity; import android.content.Intent; import android.database.Cursor; diff --git a/mobile/android/base/Favicons.java b/mobile/android/base/Favicons.java index 55b1f00dca34..4a70f4fe6783 100644 --- a/mobile/android/base/Favicons.java +++ b/mobile/android/base/Favicons.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.util.GeckoJarReader; import org.apache.http.HttpEntity; import org.apache.http.client.methods.HttpGet; diff --git a/mobile/android/base/FilePickerResultHandler.java b/mobile/android/base/FilePickerResultHandler.java index 85b2a5ab5769..566958db7ce1 100644 --- a/mobile/android/base/FilePickerResultHandler.java +++ b/mobile/android/base/FilePickerResultHandler.java @@ -4,6 +4,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.ActivityResultHandler; + import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 1ae7ef52e195..ba4ca6da2a30 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -13,6 +13,7 @@ import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.gfx.PluginLayer; import org.mozilla.gecko.gfx.PointUtils; import org.mozilla.gecko.ui.PanZoomController; +import org.mozilla.gecko.util.GeckoAsyncTask; import org.json.JSONArray; import org.json.JSONException; @@ -106,7 +107,7 @@ abstract public class GeckoApp extends GeckoActivity implements GeckoEventListener, SensorEventListener, LocationListener, GeckoApplication.ApplicationLifecycleCallbacks, - Tabs.OnTabsChangedListener + Tabs.OnTabsChangedListener, GeckoEventResponder { private static final String LOGTAG = "GeckoApp"; @@ -141,6 +142,7 @@ abstract public class GeckoApp public static boolean sIsGeckoReady = false; public static int mOrientation; private boolean mIsRestoringActivity; + private String mCurrentResponse = ""; private GeckoConnectivityReceiver mConnectivityReceiver; private GeckoBatteryManager mBatteryReceiver; @@ -714,7 +716,7 @@ abstract public class GeckoApp } void handleFaviconRequest(final String url) { - (new GeckoAsyncTask() { + (new GeckoAsyncTask(mAppContext, GeckoAppShell.getHandler()) { @Override public String doInBackground(Void... params) { return getFavicons().getFaviconUrlForPageUrl(url); @@ -1099,7 +1101,9 @@ abstract public class GeckoApp String launchPath = message.getString("launchPath"); String iconURL = message.getString("iconURL"); String uniqueURI = message.getString("uniqueURI"); - GeckoAppShell.createShortcut(name, launchPath, uniqueURI, iconURL, "webapp"); + + // installWebapp will return a File object pointing to the profile directory of the webapp + mCurrentResponse = GeckoAppShell.installWebApp(name, launchPath, uniqueURI, iconURL).toString(); } else if (event.equals("WebApps:Uninstall")) { String uniqueURI = message.getString("uniqueURI"); GeckoAppShell.uninstallWebApp(uniqueURI); @@ -1132,6 +1136,13 @@ abstract public class GeckoApp } } + public String getResponse() { + Log.i(LOGTAG, "Return " + mCurrentResponse); + String res = mCurrentResponse; + mCurrentResponse = ""; + return res; + } + void onStatePurged() { } /** diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index f38c0986482b..7edfab8d7dfe 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -16,6 +16,7 @@ import org.mozilla.gecko.gfx.RectUtils; import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.mozglue.DirectBufferAllocator; import org.mozilla.gecko.util.FloatUtils; +import org.mozilla.gecko.util.GeckoBackgroundThread; import org.json.JSONObject; @@ -540,7 +541,8 @@ public class GeckoAppShell private static void geckoLoaded() { final LayerController layerController = GeckoApp.mAppContext.getLayerController(); LayerView v = layerController.getView(); - mInputConnection = v.setInputConnectionHandler(); + mInputConnection = GeckoInputConnection.create(v); + v.setInputConnectionHandler(mInputConnection); layerController.notifyLayerClientOfGeometryChange(); } @@ -794,6 +796,13 @@ public class GeckoAppShell gRestartScheduled = true; } + public static File installWebApp(String aTitle, String aURI, String aUniqueURI, String aIconURL) { + int index = WebAppAllocator.getInstance(GeckoApp.mAppContext).findAndAllocateIndex(aUniqueURI); + GeckoProfile profile = GeckoProfile.get(GeckoApp.mAppContext, "webapp" + index); + createShortcut(aTitle, aURI, aUniqueURI, aIconURL, "webapp"); + return profile.getDir(); + } + public static Intent getWebAppIntent(String aURI, String aUniqueURI, boolean forInstall) { int index; diff --git a/mobile/android/base/GeckoAsyncTask.java b/mobile/android/base/GeckoAsyncTask.java index fdeb870c2171..c8e217658d3d 100644 --- a/mobile/android/base/GeckoAsyncTask.java +++ b/mobile/android/base/GeckoAsyncTask.java @@ -3,22 +3,27 @@ * 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; +package org.mozilla.gecko.util; + +import android.app.Activity; +import android.os.Handler; // AsyncTask runs onPostExecute on the thread it is constructed on // We construct these off of the main thread, and we want that to run // on the main UI thread, so this is a convenience class to do that public abstract class GeckoAsyncTask { - public static final int PRIORITY_NORMAL = 0; - public static final int PRIORITY_HIGH = 1; + public enum Priority { NORMAL, HIGH }; - private int mPriority; + private final Activity mActivity; + private final Handler mBackgroundThreadHandler; + private Priority mPriority = Priority.NORMAL; - public GeckoAsyncTask() { - mPriority = PRIORITY_NORMAL; + public GeckoAsyncTask(Activity activity, Handler backgroundThreadHandler) { + mActivity = activity; + mBackgroundThreadHandler = backgroundThreadHandler; } - private class BackgroundTaskRunnable implements Runnable { + private final class BackgroundTaskRunnable implements Runnable { private Params[] mParams; public BackgroundTaskRunnable(Params... params) { @@ -27,7 +32,7 @@ public abstract class GeckoAsyncTask { public void run() { final Result result = doInBackground(mParams); - GeckoApp.mAppContext.runOnUiThread(new Runnable() { + mActivity.runOnUiThread(new Runnable() { public void run() { onPostExecute(result); } @@ -35,18 +40,19 @@ public abstract class GeckoAsyncTask { } } - public void execute(final Params... params) { - if (mPriority == PRIORITY_HIGH) - GeckoAppShell.getHandler().postAtFrontOfQueue(new BackgroundTaskRunnable(params)); + public final void execute(final Params... params) { + BackgroundTaskRunnable runnable = new BackgroundTaskRunnable(params); + if (mPriority == Priority.HIGH) + mBackgroundThreadHandler.postAtFrontOfQueue(runnable); else - GeckoAppShell.getHandler().post(new BackgroundTaskRunnable(params)); + mBackgroundThreadHandler.post(runnable); } - public GeckoAsyncTask setPriority(int priority) { + public final GeckoAsyncTask setPriority(Priority priority) { mPriority = priority; return this; } protected abstract Result doInBackground(Params... params); - protected abstract void onPostExecute(Result result); + protected abstract void onPostExecute(Result result); } diff --git a/mobile/android/base/GeckoBackgroundThread.java b/mobile/android/base/GeckoBackgroundThread.java index 6bc847009175..0ec189c18c7a 100644 --- a/mobile/android/base/GeckoBackgroundThread.java +++ b/mobile/android/base/GeckoBackgroundThread.java @@ -2,14 +2,14 @@ * 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; +package org.mozilla.gecko.util; import android.os.Handler; import android.os.Looper; import java.util.concurrent.SynchronousQueue; -public class GeckoBackgroundThread extends Thread { +public final class GeckoBackgroundThread extends Thread { private static final String LOOPER_NAME = "GeckoBackgroundThread"; // Guarded by 'this'. diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index ee31569a5a6c..3926de857314 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -43,7 +43,7 @@ import android.view.inputmethod.InputMethodManager; import java.util.Timer; import java.util.TimerTask; -public class GeckoInputConnection +class GeckoInputConnection extends BaseInputConnection implements TextWatcher, InputConnectionHandler { diff --git a/mobile/android/base/GeckoJarReader.java b/mobile/android/base/GeckoJarReader.java index 2bd5452c76bc..ad7017d79c2f 100644 --- a/mobile/android/base/GeckoJarReader.java +++ b/mobile/android/base/GeckoJarReader.java @@ -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/. */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; import android.graphics.drawable.BitmapDrawable; import android.util.Log; @@ -20,9 +20,11 @@ import java.util.zip.ZipInputStream; /* Reads out of a multiple level deep jar file such as * jar:jar:file:///data/app/org.mozilla.fennec.apk!/omni.ja!/chrome/chrome/content/branding/favicon32.png */ -public class GeckoJarReader { +public final class GeckoJarReader { private static String LOGTAG = "GeckoJarReader"; + private GeckoJarReader() {} + public static BitmapDrawable getBitmapDrawable(String url) { Stack jarUrls = parseUrl(url); InputStream inputStream = null; diff --git a/mobile/android/base/GeckoProfile.java b/mobile/android/base/GeckoProfile.java index c8739d6488de..0a2b8ddb01d1 100644 --- a/mobile/android/base/GeckoProfile.java +++ b/mobile/android/base/GeckoProfile.java @@ -9,6 +9,9 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.INIParser; +import org.mozilla.gecko.util.INISection; + import android.content.Context; import android.os.SystemClock; import android.text.TextUtils; diff --git a/mobile/android/base/INIParser.java b/mobile/android/base/INIParser.java index ebae406110af..680e37bce0ae 100644 --- a/mobile/android/base/INIParser.java +++ b/mobile/android/base/INIParser.java @@ -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/. */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; -public class INIParser extends INISection { +public final class INIParser extends INISection { // default file to read and write to private File mFile = null; diff --git a/mobile/android/base/INISection.java b/mobile/android/base/INISection.java index cf9b3d72040f..7dcc9497fac5 100644 --- a/mobile/android/base/INISection.java +++ b/mobile/android/base/INISection.java @@ -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/. */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; import android.text.TextUtils; import android.util.Log; @@ -12,7 +12,7 @@ import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; -class INISection { +public class INISection { private static final String LOGTAG = "INIParser"; // default file to read and write to diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 440e92264fec..38eea169a3c3 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -21,6 +21,13 @@ MOZGLUE_JAVA_FILES := \ $(NULL) UTIL_JAVA_FILES := \ + ActivityResultHandler.java \ + ActivityResultHandlerMap.java \ + GeckoAsyncTask.java \ + GeckoBackgroundThread.java \ + GeckoJarReader.java \ + INIParser.java \ + INISection.java \ util/FloatUtils.java \ $(NULL) @@ -28,8 +35,6 @@ FENNEC_JAVA_FILES = \ AboutHomeContent.java \ AboutHomeSection.java \ ActivityHandlerHelper.java \ - ActivityResultHandler.java \ - ActivityResultHandlerMap.java \ AndroidImport.java \ AndroidImportPreference.java \ AlertNotification.java \ @@ -61,16 +66,13 @@ FENNEC_JAVA_FILES = \ GeckoApplication.java \ GeckoApp.java \ GeckoAppShell.java \ - GeckoAsyncTask.java \ GeckoBatteryManager.java \ - GeckoBackgroundThread.java \ GeckoConnectivityReceiver.java \ GeckoEvent.java \ GeckoEventListener.java \ GeckoEventResponder.java \ GeckoHalDefines.java \ GeckoInputConnection.java \ - GeckoJarReader.java \ GeckoMenu.java \ GeckoMenuInflater.java \ GeckoMenuItem.java \ @@ -80,8 +82,6 @@ FENNEC_JAVA_FILES = \ GeckoThread.java \ GlobalHistory.java \ GeckoViewsFactory.java \ - INIParser.java \ - INISection.java \ InputMethods.java \ LinkPreference.java \ LinkTextView.java \ diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index 0080f7351462..8038329aee17 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -8,6 +8,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.gfx.Layer; import org.mozilla.gecko.mozglue.DirectBufferAllocator; +import org.mozilla.gecko.util.GeckoAsyncTask; import org.json.JSONException; import org.json.JSONObject; @@ -373,7 +374,7 @@ public final class Tab { if (url == null) return; - (new GeckoAsyncTask() { + (new GeckoAsyncTask(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { if (url.equals(getURL())) { diff --git a/mobile/android/base/TabsAccessor.java b/mobile/android/base/TabsAccessor.java index d04fc8ed7f17..f2c3a40083c1 100644 --- a/mobile/android/base/TabsAccessor.java +++ b/mobile/android/base/TabsAccessor.java @@ -5,6 +5,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserContract; +import org.mozilla.gecko.util.GeckoAsyncTask; import android.content.Context; import android.database.Cursor; @@ -59,7 +60,7 @@ public final class TabsAccessor { if (listener == null) return; - (new GeckoAsyncTask () { + (new GeckoAsyncTask(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override protected Boolean doInBackground(Void... unused) { Uri uri = BrowserContract.Tabs.CONTENT_URI; @@ -87,7 +88,7 @@ public final class TabsAccessor { protected void onPostExecute(Boolean availability) { listener.areAvailable(availability); } - }).setPriority(GeckoAsyncTask.PRIORITY_HIGH).execute(); + }).setPriority(GeckoAsyncTask.Priority.HIGH).execute(); } // This method returns all tabs from all remote clients, @@ -103,7 +104,7 @@ public final class TabsAccessor { if (listener == null) return; - (new GeckoAsyncTask> () { + (new GeckoAsyncTask>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override protected List doInBackground(Void... unused) { Uri uri = BrowserContract.Tabs.CONTENT_URI; diff --git a/mobile/android/base/db/BrowserProvider.java.in b/mobile/android/base/db/BrowserProvider.java.in index 2a19f9199dff..163083c9c7c3 100644 --- a/mobile/android/base/db/BrowserProvider.java.in +++ b/mobile/android/base/db/BrowserProvider.java.in @@ -22,7 +22,6 @@ import java.util.regex.Pattern; import java.util.regex.Matcher; import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoBackgroundThread; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.R; import org.mozilla.gecko.db.BrowserContract.Bookmarks; @@ -38,6 +37,7 @@ import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.db.DBUtils; import org.mozilla.gecko.ProfileMigrator; import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.util.GeckoBackgroundThread; import android.content.ContentProvider; import android.content.ContentUris; diff --git a/mobile/android/base/db/TabsProvider.java.in b/mobile/android/base/db/TabsProvider.java.in index 2895b74423bf..11bb463b8cd5 100644 --- a/mobile/android/base/db/TabsProvider.java.in +++ b/mobile/android/base/db/TabsProvider.java.in @@ -12,7 +12,6 @@ import java.util.HashMap; import java.util.Map; import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoBackgroundThread; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.db.BrowserContract.CommonColumns; import org.mozilla.gecko.db.BrowserContract.Clients; @@ -20,6 +19,7 @@ import org.mozilla.gecko.db.BrowserContract.Tabs; import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.db.DBUtils; import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.util.GeckoBackgroundThread; import android.content.ContentProvider; import android.content.ContentUris; diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index 866a714bd8df..5c9f957e2052 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -6,7 +6,6 @@ package org.mozilla.gecko.gfx; import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.GeckoInputConnection; import android.content.Context; import android.graphics.PixelFormat; @@ -131,10 +130,8 @@ public class LayerView extends FrameLayout { mController.setViewportSize(new FloatSize(size)); } - public GeckoInputConnection setInputConnectionHandler() { - GeckoInputConnection geckoInputConnection = GeckoInputConnection.create(this); - mInputConnectionHandler = geckoInputConnection; - return geckoInputConnection; + public void setInputConnectionHandler(InputConnectionHandler inputConnectionHandler) { + mInputConnectionHandler = inputConnectionHandler; } @Override diff --git a/mobile/android/base/resources/values/dimens.xml b/mobile/android/base/resources/values/dimens.xml index 7331603d63b9..5d461b1a8c36 100644 --- a/mobile/android/base/resources/values/dimens.xml +++ b/mobile/android/base/resources/values/dimens.xml @@ -7,7 +7,7 @@ 0dp 0dp - 106dp + 110dp 200dp 32dp 20dp diff --git a/mobile/android/base/tests/testJarReader.java.in b/mobile/android/base/tests/testJarReader.java.in index a3b105c1eb8b..c1157ca8d6b5 100644 --- a/mobile/android/base/tests/testJarReader.java.in +++ b/mobile/android/base/tests/testJarReader.java.in @@ -27,7 +27,7 @@ public class testJarReader extends BaseTest { public void testJarReader() { try { ClassLoader classLoader = getActivity().getClassLoader(); - Class gjrClass = classLoader.loadClass("org.mozilla.gecko.GeckoJarReader"); + Class gjrClass = classLoader.loadClass("org.mozilla.gecko.util.GeckoJarReader"); Method getStreamMethod = gjrClass.getMethod("getStream", String.class); String appPath = getActivity().getApplication().getPackageResourcePath(); diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 12b2b6ddd86a..b32d0165db79 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -5918,7 +5918,7 @@ var WebappsUI = { }).bind(this)); break; case "webapps-sync-install": - // Wait until we know the app install worked, then make a homescreen shortcut + // Create a system notification allowing the user to launch the app DOMApplicationRegistry.getManifestFor(data.origin, (function(aManifest) { if (!aManifest) return; @@ -5930,21 +5930,6 @@ var WebappsUI = { let name = manifest.name ? converter.ConvertToUnicode(manifest.name) : converter.ConvertToUnicode(manifest.fullLaunchPath()); - // Add a homescreen shortcut -- we can't use createShortcut, since we need to pass - // a unique ID for Android webapp allocation - this.makeBase64Icon(this.getBiggestIcon(manifest.icons, Services.io.newURI(data.origin, null, null)), - function(icon) { - sendMessageToJava({ - gecko: { - type: "WebApps:Install", - name: name, - launchPath: manifest.fullLaunchPath(), - iconURL: icon, - uniqueURI: data.origin - } - })}); - - // Create a system notification allowing the user to launch the app let observer = { observe: function (aSubject, aTopic) { if (aTopic == "alertclickcallback") { @@ -6005,10 +5990,32 @@ var WebappsUI = { doInstall: function doInstall(aData) { let manifest = new DOMApplicationManifest(aData.app.manifest, aData.app.origin); let name = manifest.name ? manifest.name : manifest.fullLaunchPath(); - if (Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), name)) - DOMApplicationRegistry.confirmInstall(aData); - else + if (Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), name)) { + // Add a homescreen shortcut -- we can't use createShortcut, since we need to pass + // a unique ID for Android webapp allocation + this.makeBase64Icon(this.getBiggestIcon(manifest.icons, Services.io.newURI(aData.app.origin, null, null)), + function(icon) { + var profilePath = sendMessageToJava({ + gecko: { + type: "WebApps:Install", + name: manifest.name, + launchPath: manifest.fullLaunchPath(), + iconURL: icon, + uniqueURI: aData.app.origin + } + }); + + // if java returned a profile path to us, try to use it to pre-populate the app cache + var file = null; + if (profilePath) { + var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); + file.initWithPath(profilePath); + } + DOMApplicationRegistry.confirmInstall(aData, false, file); + }); + } else { DOMApplicationRegistry.denyInstall(aData); + } }, openURL: function openURL(aURI, aOrigin) { diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 807a4960a8fd..90f8ead1bf78 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3523,6 +3523,7 @@ pref("layers.acceleration.draw-fps", false); // Whether to animate simple opacity and transforms on the compositor pref("layers.offmainthreadcomposition.animate-opacity", false); pref("layers.offmainthreadcomposition.animate-transform", false); +pref("layers.offmainthreadcomposition.log-animations", false); #ifdef MOZ_X11 #ifdef MOZ_WIDGET_GTK2 @@ -3661,3 +3662,7 @@ pref("memory.low_memory_notification_interval_ms", 10000); pref("memory.ghost_window_timeout_seconds", 60); pref("social.enabled", false); + +// Disable idle observer fuzz, because only privileged content can access idle +// observers (bug 780507). +pref("dom.idle-observers-api.fuzz_time.disabled", true); diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index 705ea751fe13..569301bbdc06 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -1253,9 +1253,12 @@ NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **result, * searches the channel's notificationCallbacks attribute, and if the interface * is not found there, then it inspects the notificationCallbacks attribute of * the channel's loadGroup. + * + * Note: templatized only because nsIWebSocketChannel is currently not an + * nsIChannel. */ -inline void -NS_QueryNotificationCallbacks(nsIChannel *channel, +template inline void +NS_QueryNotificationCallbacks(T *channel, const nsIID &iid, void **result) { @@ -1278,9 +1281,12 @@ NS_QueryNotificationCallbacks(nsIChannel *channel, } } -/* template helper */ -template inline void -NS_QueryNotificationCallbacks(nsIChannel *channel, +// template helper: +// Note: "class C" templatized only because nsIWebSocketChannel is currently not +// an nsIChannel. + +template inline void +NS_QueryNotificationCallbacks(C *channel, nsCOMPtr &result) { NS_QueryNotificationCallbacks(channel, NS_GET_TEMPLATE_IID(T), diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index 4cc47d271eea..12cc188f4e4e 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -16,6 +16,7 @@ #include "nsStringStream.h" #include "prio.h" #include "mozilla/Util.h" // for DebugOnly +#include "SerializedLoadContext.h" namespace IPC { diff --git a/netwerk/protocol/ftp/FTPChannelChild.cpp b/netwerk/protocol/ftp/FTPChannelChild.cpp index cb809365ba91..ffe34c58d466 100644 --- a/netwerk/protocol/ftp/FTPChannelChild.cpp +++ b/netwerk/protocol/ftp/FTPChannelChild.cpp @@ -160,29 +160,8 @@ FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext) if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); - // Get info from nsILoadContext, if any - bool haveLoadContext = false; - bool isContent = false; - bool usePrivateBrowsing = false; - bool isInBrowserElement = false; - PRUint32 appId = 0; - nsCAutoString extendedOrigin; - nsCOMPtr loadContext; - NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, - NS_GET_IID(nsILoadContext), - getter_AddRefs(loadContext)); - if (loadContext) { - haveLoadContext = true; - loadContext->GetIsContent(&isContent); - loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); - loadContext->GetIsInBrowserElement(&isInBrowserElement); - loadContext->GetAppId(&appId); - loadContext->GetExtendedOrigin(mURI, extendedOrigin); - } - SendAsyncOpen(nsBaseChannel::URI(), mStartPos, mEntityID, - IPC::InputStream(mUploadStream), haveLoadContext, isContent, - usePrivateBrowsing, isInBrowserElement, appId, extendedOrigin); + IPC::InputStream(mUploadStream), IPC::SerializedLoadContext(this)); // The socket transport layer in the chrome process now has a logical ref to // us until OnStopRequest is called. diff --git a/netwerk/protocol/ftp/FTPChannelParent.cpp b/netwerk/protocol/ftp/FTPChannelParent.cpp index 66fd712eb8a6..33bbe0e26c73 100644 --- a/netwerk/protocol/ftp/FTPChannelParent.cpp +++ b/netwerk/protocol/ftp/FTPChannelParent.cpp @@ -11,6 +11,7 @@ #include "nsISupportsPriority.h" #include "nsIRedirectChannelRegistrar.h" #include "nsFtpProtocolHandler.h" +#include "mozilla/LoadContext.h" #undef LOG #define LOG(args) PR_LOG(gFTPLog, PR_LOG_DEBUG, args) @@ -20,11 +21,6 @@ namespace net { FTPChannelParent::FTPChannelParent() : mIPCClosed(false) - , mHaveLoadContext(false) - , mIsContent(false) - , mUsePrivateBrowsing(false) - , mIsInBrowserElement(false) - , mAppId(0) { nsIProtocolHandler* handler; CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ftp", &handler); @@ -48,11 +44,10 @@ FTPChannelParent::ActorDestroy(ActorDestroyReason why) // FTPChannelParent::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS5(FTPChannelParent, +NS_IMPL_ISUPPORTS4(FTPChannelParent, nsIStreamListener, nsIParentChannel, nsIInterfaceRequestor, - nsILoadContext, nsIRequestObserver); //----------------------------------------------------------------------------- @@ -64,12 +59,7 @@ FTPChannelParent::RecvAsyncOpen(const IPC::URI& aURI, const PRUint64& aStartPos, const nsCString& aEntityID, const IPC::InputStream& aUploadStream, - const bool& haveLoadContext, - const bool& isContent, - const bool& usePrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin) + const IPC::SerializedLoadContext& loadContext) { nsCOMPtr uri(aURI); @@ -104,14 +94,8 @@ FTPChannelParent::RecvAsyncOpen(const IPC::URI& aURI, if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); - // fields needed to impersonate nsILoadContext - mHaveLoadContext = haveLoadContext; - mIsContent = isContent; - mUsePrivateBrowsing = usePrivateBrowsing; - mIsInBrowserElement = isInBrowserElement; - mAppId = appId; - mExtendedOrigin = extendedOrigin; - mChannel->SetNotificationCallbacks(this); + if (loadContext.IsNotNull()) + mLoadContext = new LoadContext(loadContext); rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) @@ -248,89 +232,16 @@ NS_IMETHODIMP FTPChannelParent::GetInterface(const nsIID& uuid, void** result) { // Only support nsILoadContext if child channel's callbacks did too - if (uuid.Equals(NS_GET_IID(nsILoadContext)) && !mHaveLoadContext) { - return NS_NOINTERFACE; + if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { + NS_ADDREF(mLoadContext); + *result = static_cast(mLoadContext); + return NS_OK; } return QueryInterface(uuid, result); } -//----------------------------------------------------------------------------- -// FTPChannelParent::nsILoadContext -//----------------------------------------------------------------------------- - -NS_IMETHODIMP -FTPChannelParent::GetAssociatedWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -FTPChannelParent::GetTopWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -FTPChannelParent::IsAppOfType(PRUint32, bool*) -{ - // don't expect we need this in parent (Thunderbird/SeaMonkey specific?) - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -FTPChannelParent::GetIsContent(bool *aIsContent) -{ - NS_ENSURE_ARG_POINTER(aIsContent); - - *aIsContent = mIsContent; - return NS_OK; -} - -NS_IMETHODIMP -FTPChannelParent::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) -{ - NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); - - *aUsePrivateBrowsing = mUsePrivateBrowsing; - return NS_OK; -} - -NS_IMETHODIMP -FTPChannelParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) -{ - // We shouldn't need this on parent... - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -FTPChannelParent::GetIsInBrowserElement(bool* aIsInBrowserElement) -{ - NS_ENSURE_ARG_POINTER(aIsInBrowserElement); - - *aIsInBrowserElement = mIsInBrowserElement; - return NS_OK; -} - -NS_IMETHODIMP -FTPChannelParent::GetAppId(PRUint32* aAppId) -{ - NS_ENSURE_ARG_POINTER(aAppId); - - *aAppId = mAppId; - return NS_OK; -} - -NS_IMETHODIMP -FTPChannelParent::GetExtendedOrigin(nsIURI *aUri, nsACString &aResult) -{ - aResult = mExtendedOrigin; - return NS_OK; -} - - +//--------------------- } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/ftp/FTPChannelParent.h b/netwerk/protocol/ftp/FTPChannelParent.h index ad637d5df8bc..f7517789669f 100644 --- a/netwerk/protocol/ftp/FTPChannelParent.h +++ b/netwerk/protocol/ftp/FTPChannelParent.h @@ -22,7 +22,6 @@ namespace net { class FTPChannelParent : public PFTPChannelParent , public nsIParentChannel , public nsIInterfaceRequestor - , public nsILoadContext { public: NS_DECL_ISUPPORTS @@ -30,7 +29,6 @@ public: NS_DECL_NSISTREAMLISTENER NS_DECL_NSIPARENTCHANNEL NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSILOADCONTEXT FTPChannelParent(); virtual ~FTPChannelParent(); @@ -40,12 +38,7 @@ protected: const PRUint64& startPos, const nsCString& entityID, const IPC::InputStream& uploadStream, - const bool& haveLoadContext, - const bool& isContent, - const bool& usingPrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin) MOZ_OVERRIDE; + const IPC::SerializedLoadContext& loadContext) MOZ_OVERRIDE; virtual bool RecvConnectChannel(const PRUint32& channelId) MOZ_OVERRIDE; virtual bool RecvCancel(const nsresult& status) MOZ_OVERRIDE; virtual bool RecvSuspend() MOZ_OVERRIDE; @@ -57,14 +50,7 @@ protected: bool mIPCClosed; - // fields for impersonating nsILoadContext - bool mHaveLoadContext : 1; - bool mIsContent : 1; - bool mUsePrivateBrowsing : 1; - bool mIsInBrowserElement : 1; - - PRUint32 mAppId; - nsCString mExtendedOrigin; + nsCOMPtr mLoadContext; }; } // namespace net diff --git a/netwerk/protocol/ftp/PFTPChannel.ipdl b/netwerk/protocol/ftp/PFTPChannel.ipdl index 7f6ce79f9925..0b390512a00c 100644 --- a/netwerk/protocol/ftp/PFTPChannel.ipdl +++ b/netwerk/protocol/ftp/PFTPChannel.ipdl @@ -11,6 +11,7 @@ include "mozilla/net/NeckoMessageUtils.h"; using IPC::URI; using IPC::InputStream; +using IPC::SerializedLoadContext; using PRTime; namespace mozilla { @@ -27,12 +28,8 @@ parent: PRUint64 startPos, nsCString entityID, InputStream uploadStream, - bool haveLoadContext, - bool isContent, - bool usePrivateBrowsing, - bool isInBrowserElement, - PRUint32 appID, - nsCString extendedOrigin); + SerializedLoadContext loadContext); + ConnectChannel(PRUint32 channelId); Cancel(nsresult status); Suspend(); diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index d70f69bcc32f..5fe6863298af 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1015,24 +1015,6 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) } } - // Get info from nsILoadContext, if any - bool haveLoadContext = false; - bool isContent = false; - bool usePrivateBrowsing = false; - bool isInBrowserElement = false; - PRUint32 appId = 0; - nsCAutoString extendedOrigin; - nsCOMPtr loadContext; - GetCallback(loadContext); - if (loadContext) { - haveLoadContext = true; - loadContext->GetIsContent(&isContent); - loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); - loadContext->GetIsInBrowserElement(&isInBrowserElement); - loadContext->GetAppId(&appId); - loadContext->GetExtendedOrigin(mURI, extendedOrigin); - } - // // Send request to the chrome process... // @@ -1059,8 +1041,7 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) mPriority, mRedirectionLimit, mAllowPipelining, mForceAllowThirdPartyCookie, mSendResumeAt, mStartPos, mEntityID, mChooseApplicationCache, - appCacheClientId, mAllowSpdy, haveLoadContext, isContent, - usePrivateBrowsing, isInBrowserElement, appId, extendedOrigin); + appCacheClientId, mAllowSpdy, IPC::SerializedLoadContext(this)); return NS_OK; } diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 89b2c2cdbba2..07408ea2e7b8 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -22,6 +22,7 @@ #include "nsIApplicationCacheService.h" #include "nsIOfflineCacheUpdate.h" #include "nsIRedirectChannelRegistrar.h" +#include "mozilla/LoadContext.h" #include "prinit.h" namespace mozilla { @@ -35,11 +36,6 @@ HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding) , mSentRedirect1Begin(false) , mSentRedirect1BeginFailed(false) , mReceivedRedirect2Verify(false) - , mHaveLoadContext(false) - , mIsContent(false) - , mUsePrivateBrowsing(false) - , mIsInBrowserElement(false) - , mAppId(0) { // Ensure gHttpHandler is initialized: we need the atom table up and running. nsIHttpProtocolHandler* handler; @@ -67,8 +63,7 @@ HttpChannelParent::ActorDestroy(ActorDestroyReason why) // HttpChannelParent::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS7(HttpChannelParent, - nsILoadContext, +NS_IMPL_ISUPPORTS6(HttpChannelParent, nsIInterfaceRequestor, nsIProgressEventSink, nsIRequestObserver, @@ -92,8 +87,10 @@ HttpChannelParent::GetInterface(const nsIID& aIID, void **result) } // Only support nsILoadContext if child channel's callbacks did too - if (aIID.Equals(NS_GET_IID(nsILoadContext)) && !mHaveLoadContext) { - return NS_NOINTERFACE; + if (aIID.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { + NS_ADDREF(mLoadContext); + *result = static_cast(mLoadContext); + return NS_OK; } return QueryInterface(aIID, result); @@ -123,12 +120,7 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI, const bool& chooseApplicationCache, const nsCString& appCacheClientID, const bool& allowSpdy, - const bool& haveLoadContext, - const bool& isContent, - const bool& usePrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin) + const IPC::SerializedLoadContext& loadContext) { nsCOMPtr uri(aURI); nsCOMPtr originalUri(aOriginalURI); @@ -150,13 +142,8 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI, if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); - // fields needed to impersonate nsILoadContext - mHaveLoadContext = haveLoadContext; - mIsContent = isContent; - mUsePrivateBrowsing = usePrivateBrowsing; - mIsInBrowserElement = isInBrowserElement; - mAppId = appId; - mExtendedOrigin = extendedOrigin; + if (loadContext.IsNotNull()) + mLoadContext = new LoadContext(loadContext); nsHttpChannel *httpChan = static_cast(mChannel.get()); @@ -608,79 +595,4 @@ HttpChannelParent::CompleteRedirect(bool succeeded) return NS_OK; } -//----------------------------------------------------------------------------- -// HttpChannelParent::nsILoadContext -//----------------------------------------------------------------------------- - -NS_IMETHODIMP -HttpChannelParent::GetAssociatedWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -HttpChannelParent::GetTopWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -HttpChannelParent::IsAppOfType(PRUint32, bool*) -{ - // don't expect we need this in parent (Thunderbird/SeaMonkey specific?) - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -HttpChannelParent::GetIsContent(bool *aIsContent) -{ - NS_ENSURE_ARG_POINTER(aIsContent); - - *aIsContent = mIsContent; - return NS_OK; -} - -NS_IMETHODIMP -HttpChannelParent::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) -{ - NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); - - *aUsePrivateBrowsing = mUsePrivateBrowsing; - return NS_OK; -} - -NS_IMETHODIMP -HttpChannelParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) -{ - // We shouldn't need this on parent... - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -HttpChannelParent::GetIsInBrowserElement(bool* aIsInBrowserElement) -{ - NS_ENSURE_ARG_POINTER(aIsInBrowserElement); - - *aIsInBrowserElement = mIsInBrowserElement; - return NS_OK; -} - -NS_IMETHODIMP -HttpChannelParent::GetAppId(PRUint32* aAppId) -{ - NS_ENSURE_ARG_POINTER(aAppId); - - *aAppId = mAppId; - return NS_OK; -} - -NS_IMETHODIMP -HttpChannelParent::GetExtendedOrigin(nsIURI *aUri, nsACString &aResult) -{ - aResult = mExtendedOrigin; - return NS_OK; -} - }} // mozilla::net diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index c76efdac63f8..2d0d9cedcb24 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -31,7 +31,6 @@ class HttpChannelParent : public PHttpChannelParent , public nsIParentRedirectingChannel , public nsIProgressEventSink , public nsIInterfaceRequestor - , public nsILoadContext { public: NS_DECL_ISUPPORTS @@ -41,7 +40,6 @@ public: NS_DECL_NSIPARENTREDIRECTINGCHANNEL NS_DECL_NSIPROGRESSEVENTSINK NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSILOADCONTEXT HttpChannelParent(PBrowserParent* iframeEmbedding); virtual ~HttpChannelParent(); @@ -66,12 +64,7 @@ protected: const bool& chooseApplicationCache, const nsCString& appCacheClientID, const bool& allowSpdy, - const bool & haveLoadContext, - const bool & isContent, - const bool& usingPrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin); + const IPC::SerializedLoadContext& loadContext) MOZ_OVERRIDE; virtual bool RecvConnectChannel(const PRUint32& channelId); virtual bool RecvSetPriority(const PRUint16& priority); @@ -115,14 +108,7 @@ private: bool mSentRedirect1BeginFailed : 1; bool mReceivedRedirect2Verify : 1; - // fields for impersonating nsILoadContext - bool mHaveLoadContext : 1; - bool mIsContent : 1; - bool mUsePrivateBrowsing : 1; - bool mIsInBrowserElement : 1; - - PRUint32 mAppId; - nsCString mExtendedOrigin; + nsCOMPtr mLoadContext; }; } // namespace net diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl index 93a2fd1ef72e..8b1800472f4c 100644 --- a/netwerk/protocol/http/PHttpChannel.ipdl +++ b/netwerk/protocol/http/PHttpChannel.ipdl @@ -17,6 +17,7 @@ using nsHttpResponseHead; using nsHttpAtom; using IPC::URI; using IPC::InputStream; +using IPC::SerializedLoadContext; using PRNetAddr; namespace mozilla { @@ -50,13 +51,7 @@ parent: bool chooseApplicationCache, nsCString appCacheClientID, bool allowSpdy, - // Fields for imitating a nsILoadContext - bool haveLoadContext, - bool isContent, - bool usePrivateBrowsing, - bool isInBrowserElement, - PRUint32 appID, - nsCString extendedOrigin); + SerializedLoadContext loadContext); // Used to connect redirected-to channel on the parent with redirected-to // channel on the child. diff --git a/netwerk/protocol/http/nsHttp.h b/netwerk/protocol/http/nsHttp.h index 99755c810c76..a1376b810546 100644 --- a/netwerk/protocol/http/nsHttp.h +++ b/netwerk/protocol/http/nsHttp.h @@ -20,7 +20,7 @@ // 2) #include IPDL boilerplate, and then undef LOG so our LOG wins. // 3) nsNetModule.cpp does its own crazy stuff with #including prlog.h // multiple times; allow it to define ALLOW_LATE_NSHTTP_H_INCLUDE to bypass -// check. +// check. #if defined(PR_LOG) && !defined(ALLOW_LATE_NSHTTP_H_INCLUDE) #error "If nsHttp.h #included it must come before any IPDL-generated files or other files that #include prlog.h" #endif @@ -181,7 +181,7 @@ struct nsHttp } // Declare all atoms - // + // // The atom names and values are stored in nsHttpAtomList.h and are brought // to you by the magic of C preprocessing. Add new atoms to nsHttpAtomList // and all support logic will be auto-generated. @@ -204,7 +204,7 @@ PRTimeToSeconds(PRTime t_usec) #define NowInSeconds() PRTimeToSeconds(PR_Now()) // round q-value to one decimal place; return most significant digit as uint. -#define QVAL_TO_UINT(q) ((unsigned int) ((q + 0.0005) * 1000.0)) +#define QVAL_TO_UINT(q) ((unsigned int) ((q + 0.05) * 10.0)) #define HTTP_LWS " \t" #define HTTP_HEADER_VALUE_SEPS HTTP_LWS "," diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index fc25841a6dce..1f97caa9b277 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -234,7 +234,7 @@ nsHttpHandler::Init() if (prefBranch) { prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true); prefBranch->AddObserver(UA_PREF_PREFIX, this, true); - prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true); + prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true); prefBranch->AddObserver(NETWORK_ENABLEIDN, this, true); prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true); prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true); @@ -292,8 +292,8 @@ nsHttpHandler::Init() // Bring alive the objects in the http-protocol-startup category NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY, static_cast(static_cast(this)), - NS_HTTP_STARTUP_TOPIC); - + NS_HTTP_STARTUP_TOPIC); + mObserverService = mozilla::services::GetObserverService(); if (mObserverService) { mObserverService->AddObserver(this, "profile-change-net-teardown", true); @@ -303,7 +303,7 @@ nsHttpHandler::Init() mObserverService->AddObserver(this, "net:prune-dead-connections", true); mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true); } - + return NS_OK; } @@ -363,10 +363,10 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request, // transparent proxies) can result. // // However, we need to send something so that we can use keepalive - // with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when + // with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when // we're talking to an http proxy, and "Connection:" otherwise. // We no longer send the Keep-Alive request header. - + NS_NAMED_LITERAL_CSTRING(close, "close"); NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive"); @@ -435,7 +435,7 @@ nsHttpHandler::GetCookieService() return mCookieService; } -nsresult +nsresult nsHttpHandler::GetIOService(nsIIOService** result) { NS_ADDREF(*result = mIOService); @@ -452,7 +452,7 @@ nsHttpHandler::Get32BitsOfPseudoRandom() // 15 or 31 bits are common amounts. PR_STATIC_ASSERT(RAND_MAX >= 0xfff); - + #if RAND_MAX < 0xffffU return ((PRUint16) rand() << 20) | (((PRUint16) rand() & 0xfff) << 8) | @@ -521,10 +521,10 @@ nsHttpHandler::BuildUserAgent() // preallocate to worst-case size, which should always be better // than if we didn't preallocate at all. - mUserAgent.SetCapacity(mLegacyAppName.Length() + - mLegacyAppVersion.Length() + + mUserAgent.SetCapacity(mLegacyAppName.Length() + + mLegacyAppVersion.Length() + #ifndef UA_SPARE_PLATFORM - mPlatform.Length() + + mPlatform.Length() + #endif mOscpu.Length() + mMisc.Length() + @@ -674,7 +674,7 @@ nsHttpHandler::InitUserAgentComponents() } #elif defined (XP_UNIX) struct utsname name; - + int ret = uname(&name); if (ret >= 0) { nsCAutoString buf; @@ -981,7 +981,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) if (NS_SUCCEEDED(rv)) SetAccept(accept); } - + if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) { nsXPIDLCString acceptEncodings; rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"), @@ -1034,7 +1034,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) mEnforceAssocReq = cVar; } - // enable Persistent caching for HTTPS - bug#205921 + // enable Persistent caching for HTTPS - bug#205921 if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) { cVar = false; rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar); @@ -1141,7 +1141,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) pls->ToString(getter_Copies(uval)); if (uval) SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get()); - } + } } // @@ -1259,8 +1259,8 @@ PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLangua if (*token != '\0') { comma = n++ != 0 ? "," : ""; // delimiter if not first item PRUint32 u = QVAL_TO_UINT(q); - if (u < 1000) - wrote = PR_snprintf(p2, available, "%s%s;q=0.%03u", comma, token, u); + if (u < 10) + wrote = PR_snprintf(p2, available, "%s%s;q=0.%u", comma, token, u); else wrote = PR_snprintf(p2, available, "%s%s", comma, token); q -= dec; @@ -1278,7 +1278,7 @@ PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLangua } nsresult -nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages) +nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages) { nsCAutoString buf; nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf); @@ -1288,14 +1288,14 @@ nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages) } nsresult -nsHttpHandler::SetAccept(const char *aAccept) +nsHttpHandler::SetAccept(const char *aAccept) { mAccept = aAccept; return NS_OK; } nsresult -nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings) +nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings) { mAcceptEncodings = aAcceptEncodings; return NS_OK; @@ -1373,10 +1373,10 @@ nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result) return NewProxiedChannel(uri, nullptr, result); } -NS_IMETHODIMP +NS_IMETHODIMP nsHttpHandler::AllowPort(PRInt32 port, const char *scheme, bool *_retval) { - // don't override anything. + // don't override anything. *_retval = false; return NS_OK; } @@ -1394,7 +1394,7 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri, LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n", givenProxyInfo)); - + nsCOMPtr proxyInfo; if (givenProxyInfo) { proxyInfo = do_QueryInterface(givenProxyInfo); @@ -1532,7 +1532,7 @@ nsHttpHandler::Observe(nsISupports *subject, if (uri && mConnMgr) mConnMgr->ReportFailedToProcess(uri); } - + return NS_OK; } @@ -1547,7 +1547,7 @@ nsHttpHandler::SpeculativeConnect(nsIURI *aURI, bool isStsHost = false; if (!stss) return NS_OK; - + nsCOMPtr clone; if (NS_SUCCEEDED(stss->IsStsURI(aURI, &isStsHost)) && isStsHost) { if (NS_SUCCEEDED(aURI->Clone(getter_AddRefs(clone)))) { @@ -1657,7 +1657,7 @@ nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval) NS_IMETHODIMP nsHttpsHandler::AllowPort(PRInt32 aPort, const char *aScheme, bool *_retval) { - // don't override anything. + // don't override anything. *_retval = false; return NS_OK; } diff --git a/netwerk/protocol/websocket/PWebSocket.ipdl b/netwerk/protocol/websocket/PWebSocket.ipdl index 5bf9b1598b30..6b89a850168d 100644 --- a/netwerk/protocol/websocket/PWebSocket.ipdl +++ b/netwerk/protocol/websocket/PWebSocket.ipdl @@ -12,6 +12,7 @@ include "mozilla/net/NeckoMessageUtils.h"; using IPC::URI; using IPC::InputStream; +using IPC::SerializedLoadContext; namespace mozilla { namespace net { @@ -26,13 +27,7 @@ parent: nsCString aOrigin, nsCString aProtocol, bool aSecure, - // Fields for imitating a nsILoadContext - bool haveLoadContext, - bool isContent, - bool usePrivateBrowsing, - bool isInBrowserElement, - PRUint32 appID, - nsCString extendedOrigin); + SerializedLoadContext loadContext); Close(PRUint16 code, nsCString reason); SendMsg(nsCString aMsg); SendBinaryMsg(nsCString aMsg); diff --git a/netwerk/protocol/websocket/WebSocketChannelChild.cpp b/netwerk/protocol/websocket/WebSocketChannelChild.cpp index 65112925b5fa..b703a988908f 100644 --- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp @@ -328,33 +328,12 @@ WebSocketChannelChild::AsyncOpen(nsIURI *aURI, tabChild = static_cast(iTabChild.get()); } - // Get info from nsILoadContext, if any - bool haveLoadContext = false; - bool isContent = false; - bool usePrivateBrowsing = false; - bool isInBrowserElement = false; - PRUint32 appId = 0; - nsCAutoString extendedOrigin; - nsCOMPtr loadContext; - NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, - NS_GET_IID(nsILoadContext), - getter_AddRefs(loadContext)); - if (loadContext) { - haveLoadContext = true; - loadContext->GetIsContent(&isContent); - loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); - loadContext->GetIsInBrowserElement(&isInBrowserElement); - loadContext->GetAppId(&appId); - loadContext->GetExtendedOrigin(mURI, extendedOrigin); - } - // Corresponding release in DeallocPWebSocket AddIPDLReference(); gNeckoChild->SendPWebSocketConstructor(this, tabChild); if (!SendAsyncOpen(aURI, nsCString(aOrigin), mProtocol, mEncrypted, - haveLoadContext, isContent, usePrivateBrowsing, - isInBrowserElement, appId, extendedOrigin)) + IPC::SerializedLoadContext(this))) return NS_ERROR_UNEXPECTED; mOriginalURI = aURI; diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.cpp b/netwerk/protocol/websocket/WebSocketChannelParent.cpp index 41e5b48bc68a..a0d79367f025 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp @@ -7,23 +7,18 @@ #include "WebSocketLog.h" #include "WebSocketChannelParent.h" #include "nsIAuthPromptProvider.h" +#include "mozilla/LoadContext.h" namespace mozilla { namespace net { -NS_IMPL_THREADSAFE_ISUPPORTS3(WebSocketChannelParent, +NS_IMPL_THREADSAFE_ISUPPORTS2(WebSocketChannelParent, nsIWebSocketListener, - nsILoadContext, nsIInterfaceRequestor) WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider) : mAuthProvider(aAuthProvider) , mIPCOpen(true) - , mHaveLoadContext(false) - , mIsContent(false) - , mUsePrivateBrowsing(false) - , mIsInBrowserElement(false) - , mAppId(0) { #if defined(PR_LOGGING) if (!webSocketLog) @@ -49,12 +44,7 @@ WebSocketChannelParent::RecvAsyncOpen(const IPC::URI& aURI, const nsCString& aOrigin, const nsCString& aProtocol, const bool& aSecure, - const bool& haveLoadContext, - const bool& isContent, - const bool& usePrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin) + const IPC::SerializedLoadContext& loadContext) { LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this)); nsresult rv; @@ -68,13 +58,9 @@ WebSocketChannelParent::RecvAsyncOpen(const IPC::URI& aURI, if (NS_FAILED(rv)) goto fail; - // fields needed to impersonate nsILoadContext - mHaveLoadContext = haveLoadContext; - mIsContent = isContent; - mUsePrivateBrowsing = usePrivateBrowsing; - mIsInBrowserElement = isInBrowserElement; - mAppId = appId; - mExtendedOrigin = extendedOrigin; + if (loadContext.IsNotNull()) + mLoadContext = new LoadContext(loadContext); + rv = mChannel->SetNotificationCallbacks(this); if (NS_FAILED(rv)) goto fail; @@ -229,89 +215,15 @@ WebSocketChannelParent::GetInterface(const nsIID & iid, void **result) iid, result); // Only support nsILoadContext if child channel's callbacks did too - if (iid.Equals(NS_GET_IID(nsILoadContext)) && !mHaveLoadContext) { - return NS_NOINTERFACE; + if (iid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { + NS_ADDREF(mLoadContext); + *result = static_cast(mLoadContext); + return NS_OK; } return QueryInterface(iid, result); } -//----------------------------------------------------------------------------- -// WebSocketChannelParent::nsILoadContext -//----------------------------------------------------------------------------- - -NS_IMETHODIMP -WebSocketChannelParent::GetAssociatedWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetTopWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WebSocketChannelParent::IsAppOfType(PRUint32, bool*) -{ - // don't expect we need this in parent (Thunderbird/SeaMonkey specific?) - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetIsContent(bool *aIsContent) -{ - NS_ENSURE_ARG_POINTER(aIsContent); - - *aIsContent = mIsContent; - return NS_OK; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) -{ - NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); - - *aUsePrivateBrowsing = mUsePrivateBrowsing; - return NS_OK; -} - -NS_IMETHODIMP -WebSocketChannelParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) -{ - // We shouldn't need this on parent... - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetIsInBrowserElement(bool* aIsInBrowserElement) -{ - NS_ENSURE_ARG_POINTER(aIsInBrowserElement); - - *aIsInBrowserElement = mIsInBrowserElement; - return NS_OK; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetAppId(PRUint32* aAppId) -{ - NS_ENSURE_ARG_POINTER(aAppId); - - *aAppId = mAppId; - return NS_OK; -} - -NS_IMETHODIMP -WebSocketChannelParent::GetExtendedOrigin(nsIURI *aUri, - nsACString &aResult) -{ - aResult = mExtendedOrigin; - return NS_OK; -} - } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.h b/netwerk/protocol/websocket/WebSocketChannelParent.h index 3794ae7810c2..92984c9bd081 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.h +++ b/netwerk/protocol/websocket/WebSocketChannelParent.h @@ -21,14 +21,12 @@ namespace net { class WebSocketChannelParent : public PWebSocketParent, public nsIWebSocketListener, - public nsIInterfaceRequestor, - public nsILoadContext + public nsIInterfaceRequestor { public: NS_DECL_ISUPPORTS NS_DECL_NSIWEBSOCKETLISTENER NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSILOADCONTEXT WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider); @@ -37,12 +35,7 @@ class WebSocketChannelParent : public PWebSocketParent, const nsCString& aOrigin, const nsCString& aProtocol, const bool& aSecure, - const bool& haveLoadContext, - const bool& isContent, - const bool& usingPrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin); + const IPC::SerializedLoadContext& loadContext); bool RecvClose(const PRUint16 & code, const nsCString & reason); bool RecvSendMsg(const nsCString& aMsg); bool RecvSendBinaryMsg(const nsCString& aMsg); @@ -54,16 +47,9 @@ class WebSocketChannelParent : public PWebSocketParent, nsCOMPtr mAuthProvider; nsCOMPtr mChannel; + nsCOMPtr mLoadContext; bool mIPCOpen; - // fields for impersonating nsILoadContext - bool mHaveLoadContext : 1; - bool mIsContent : 1; - bool mUsePrivateBrowsing : 1; - bool mIsInBrowserElement : 1; - - PRUint32 mAppId; - nsCString mExtendedOrigin; }; } // namespace net diff --git a/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl b/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl index b4cc5b1050e7..4477969da2a4 100644 --- a/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl +++ b/netwerk/protocol/wyciwyg/PWyciwygChannel.ipdl @@ -7,6 +7,7 @@ include protocol PNecko; include "mozilla/net/NeckoMessageUtils.h"; using IPC::URI; +using IPC::SerializedLoadContext; namespace mozilla { namespace net { @@ -20,15 +21,9 @@ parent: __delete__(); Init(URI uri); - AsyncOpen(URI originalURI, - PRUint32 loadFlags, - // Fields for imitating a nsILoadContext - bool haveLoadContext, - bool isContent, - bool usePrivateBrowsing, - bool isInBrowserElement, - PRUint32 appID, - nsCString extendedOrigin); + AsyncOpen(URI originalURI, + PRUint32 loadFlags, + SerializedLoadContext loadContext); // methods corresponding to those of nsIWyciwygChannel WriteToCacheEntry(nsString data); diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp index 81911ff596cd..828b1980b582 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp @@ -562,28 +562,8 @@ WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aConte if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); - // Get info from nsILoadContext, if any - bool haveLoadContext = false; - bool isContent = false; - bool usePrivateBrowsing = false; - bool isInBrowserElement = false; - PRUint32 appId = 0; - nsCAutoString extendedOrigin; - nsCOMPtr loadContext; - NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, - NS_GET_IID(nsILoadContext), - getter_AddRefs(loadContext)); - if (loadContext) { - haveLoadContext = true; - loadContext->GetIsContent(&isContent); - loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); - loadContext->GetIsInBrowserElement(&isInBrowserElement); - loadContext->GetAppId(&appId); - loadContext->GetExtendedOrigin(mURI, extendedOrigin); - } - - SendAsyncOpen(IPC::URI(mOriginalURI), mLoadFlags, haveLoadContext, isContent, - usePrivateBrowsing, isInBrowserElement, appId, extendedOrigin); + SendAsyncOpen(IPC::URI(mOriginalURI), mLoadFlags, + IPC::SerializedLoadContext(this)); mState = WCC_OPENED; diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp index f83df72a6cd8..26107e0fe244 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp @@ -11,17 +11,13 @@ #include "nsCharsetSource.h" #include "nsISerializable.h" #include "nsSerializationHelper.h" +#include "mozilla/LoadContext.h" namespace mozilla { namespace net { WyciwygChannelParent::WyciwygChannelParent() : mIPCClosed(false) - , mHaveLoadContext(false) - , mIsContent(false) - , mUsePrivateBrowsing(false) - , mIsInBrowserElement(false) - , mAppId(0) { #if defined(PR_LOGGING) if (!gWyciwygLog) @@ -45,10 +41,9 @@ WyciwygChannelParent::ActorDestroy(ActorDestroyReason why) // WyciwygChannelParent::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS4(WyciwygChannelParent, +NS_IMPL_ISUPPORTS3(WyciwygChannelParent, nsIStreamListener, nsIInterfaceRequestor, - nsILoadContext, nsIRequestObserver); //----------------------------------------------------------------------------- @@ -86,12 +81,7 @@ WyciwygChannelParent::RecvInit(const IPC::URI& aURI) bool WyciwygChannelParent::RecvAsyncOpen(const IPC::URI& aOriginal, const PRUint32& aLoadFlags, - const bool& haveLoadContext, - const bool& isContent, - const bool& usePrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin) + const IPC::SerializedLoadContext& loadContext) { nsCOMPtr original(aOriginal); @@ -110,14 +100,8 @@ WyciwygChannelParent::RecvAsyncOpen(const IPC::URI& aOriginal, if (NS_FAILED(rv)) return SendCancelEarly(rv); - // fields needed to impersonate nsILoadContext - mHaveLoadContext = haveLoadContext; - mIsContent = isContent; - mUsePrivateBrowsing = usePrivateBrowsing; - mIsInBrowserElement = isInBrowserElement; - mAppId = appId; - mExtendedOrigin = extendedOrigin; - mChannel->SetNotificationCallbacks(this); + if (loadContext.IsNotNull()) + mLoadContext = new LoadContext(loadContext); rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) @@ -267,88 +251,14 @@ NS_IMETHODIMP WyciwygChannelParent::GetInterface(const nsIID& uuid, void** result) { // Only support nsILoadContext if child channel's callbacks did too - if (uuid.Equals(NS_GET_IID(nsILoadContext)) && !mHaveLoadContext) { - return NS_NOINTERFACE; + if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { + NS_ADDREF(mLoadContext); + *result = static_cast(mLoadContext); + return NS_OK; } return QueryInterface(uuid, result); } -//----------------------------------------------------------------------------- -// WyciwygChannelParent::nsILoadContext -//----------------------------------------------------------------------------- - -NS_IMETHODIMP -WyciwygChannelParent::GetAssociatedWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetTopWindow(nsIDOMWindow**) -{ - // can't support this in the parent process - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WyciwygChannelParent::IsAppOfType(PRUint32, bool*) -{ - // don't expect we need this in parent (Thunderbird/SeaMonkey specific?) - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetIsContent(bool *aIsContent) -{ - NS_ENSURE_ARG_POINTER(aIsContent); - - *aIsContent = mIsContent; - return NS_OK; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) -{ - NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing); - - *aUsePrivateBrowsing = mUsePrivateBrowsing; - return NS_OK; -} - -NS_IMETHODIMP -WyciwygChannelParent::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) -{ - // We shouldn't need this on parent... - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetIsInBrowserElement(bool* aIsInBrowserElement) -{ - NS_ENSURE_ARG_POINTER(aIsInBrowserElement); - - *aIsInBrowserElement = mIsInBrowserElement; - return NS_OK; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetAppId(PRUint32* aAppId) -{ - NS_ENSURE_ARG_POINTER(aAppId); - - *aAppId = mAppId; - return NS_OK; -} - -NS_IMETHODIMP -WyciwygChannelParent::GetExtendedOrigin(nsIURI *aUri, - nsACString &aResult) -{ - aResult = mExtendedOrigin; - return NS_OK; -} - }} // mozilla::net diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h index 187857ff09a5..a660a1658bc8 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h @@ -19,14 +19,12 @@ namespace net { class WyciwygChannelParent : public PWyciwygChannelParent , public nsIStreamListener , public nsIInterfaceRequestor - , public nsILoadContext { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSILOADCONTEXT WyciwygChannelParent(); virtual ~WyciwygChannelParent(); @@ -35,12 +33,7 @@ protected: virtual bool RecvInit(const IPC::URI& uri); virtual bool RecvAsyncOpen(const IPC::URI& original, const PRUint32& loadFlags, - const bool& haveLoadContext, - const bool& isContent, - const bool& usingPrivateBrowsing, - const bool& isInBrowserElement, - const PRUint32& appId, - const nsCString& extendedOrigin); + const IPC::SerializedLoadContext& loadContext); virtual bool RecvWriteToCacheEntry(const nsString& data); virtual bool RecvCloseCacheEntry(const nsresult& reason); virtual bool RecvSetCharsetAndSource(const PRInt32& source, @@ -52,15 +45,7 @@ protected: nsCOMPtr mChannel; bool mIPCClosed; - - // fields for impersonating nsILoadContext - bool mHaveLoadContext : 1; - bool mIsContent : 1; - bool mUsePrivateBrowsing : 1; - bool mIsInBrowserElement : 1; - - PRUint32 mAppId; - nsCString mExtendedOrigin; + nsCOMPtr mLoadContext; }; } // namespace net diff --git a/netwerk/test/browser/browser_NetUtil.js b/netwerk/test/browser/browser_NetUtil.js index fe6ac4da2e5e..7aa8d7b39e89 100644 --- a/netwerk/test/browser/browser_NetUtil.js +++ b/netwerk/test/browser/browser_NetUtil.js @@ -8,6 +8,10 @@ Components.utils.import("resource://gre/modules/NetUtil.jsm"); function test() { waitForExplicitFinish(); + // We overload this test to include verifying that httpd.js is + // importable as a testing-only JS module. + Components.utils.import("resource://testing-common/httpd.js", {}); + nextTest(); } diff --git a/netwerk/test/unit/test_header_Accept-Language.js b/netwerk/test/unit/test_header_Accept-Language.js deleted file mode 100644 index b59313440964..000000000000 --- a/netwerk/test/unit/test_header_Accept-Language.js +++ /dev/null @@ -1,44 +0,0 @@ -// -// HTTP Accept-Language header test -// - -const Cc = Components.classes; -const Ci = Components.interfaces; - -var testpath = "/bug672448"; - -function run_test() { - test_accepted_languages(); -} - -function test_accepted_languages() { - let channel = setupChannel(testpath); - - let AcceptLanguage = channel.getRequestHeader("Accept-Language"); - - let acceptedLanguages = AcceptLanguage.split(","); - - for( let i = 0; i < acceptedLanguages.length; i++ ) { - let acceptedLanguage, qualityValue; - - try { - [_, acceptedLanguage, qualityValue] = acceptedLanguages[i].trim().match(/^([a-z0-9_-]*?)(?:;q=([0-9.]+))?$/i); - } catch(e) { - do_print("Invalid language tag or quality value: " + e); - } - - if( i == 0 ) { - do_check_eq(qualityValue, undefined); // First language shouldn't have a quality value. - } else { - do_check_eq(qualityValue.length, 5); // All other languages should have quality value of the format '0.123'. - } - } -} - -function setupChannel(path) { - let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - let chan = ios.newChannel("http://localhost:4444" + path, "", null); - chan.QueryInterface(Ci.nsIHttpChannel); - chan.requestMethod = "GET"; - return chan; -} diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index 91cc803aead6..d87f4cd604f2 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -42,7 +42,7 @@ skip-if = os == "android" [test_bug455311.js] [test_bug455598.js] [test_bug468426.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_bug468594.js] [test_bug470716.js] @@ -53,7 +53,7 @@ skip-if = os == "android" [test_bug490095.js] [test_bug504014.js] [test_bug510359.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_bug515583.js] [test_bug528292.js] @@ -71,16 +71,16 @@ skip-if = os == "android" [test_bug652761.js] [test_bug651100.js] # Bug 675044: test fails consistently on Android -fail-if = os == "android" +fail-if = os == "android" [test_bug654926.js] # Bug 675049: test fails consistently on Android -fail-if = os == "android" +fail-if = os == "android" [test_bug654926_doom_and_read.js] # Bug 675049: test fails consistently on Android -fail-if = os == "android" +fail-if = os == "android" [test_bug654926_test_seek.js] # Bug 675049: test fails consistently on Android -fail-if = os == "android" +fail-if = os == "android" [test_bug659569.js] [test_bug660066.js] [test_bug667907.js] @@ -103,28 +103,28 @@ fail-if = os == "android" [test_extract_charset_from_content_type.js] [test_force_sniffing.js] [test_fallback_no-cache-entry_canceled.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_no-cache-entry_passing.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_redirect-to-different-origin_canceled.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_redirect-to-different-origin_passing.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_request-error_canceled.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_request-error_passing.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_response-error_canceled.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_fallback_response-error_passing.js] -# Bug 675039: test hangs consistently on Android +# Bug 675039: test hangs consistently on Android skip-if = os == "android" [test_file_partial_inputstream.js] [test_file_protocol.js] @@ -132,7 +132,6 @@ skip-if = os == "android" [test_gre_resources.js] [test_gzipped_206.js] [test_head.js] -[test_header_Accept-Language.js] [test_headers.js] [test_http_headers.js] [test_httpcancel.js] diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 81d3faf6b5ce..4eb65211f288 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -4,6 +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 "nsDOMError.h" #include "nsHtml5TreeOpExecutor.h" #include "nsScriptLoader.h" #include "nsIMarkupDocumentViewer.h" diff --git a/security/manager/pki/src/nsPKIParamBlock.cpp b/security/manager/pki/src/nsPKIParamBlock.cpp index 220f216f18d1..6fff5021cb05 100644 --- a/security/manager/pki/src/nsPKIParamBlock.cpp +++ b/security/manager/pki/src/nsPKIParamBlock.cpp @@ -83,7 +83,9 @@ nsPKIParamBlock::SetISupportAtIndex(PRInt32 index, nsISupports *object) return NS_ERROR_OUT_OF_MEMORY; } } - return mSupports->InsertElementAt(object, index-1); + // Ignore any InsertElementAt error, because this function always did that + mSupports->InsertElementAt(object, index-1); + return NS_OK; } /* nsISupports getISupportAtIndex (in PRInt32 index); */ diff --git a/security/manager/ssl/src/nsCertOverrideService.cpp b/security/manager/ssl/src/nsCertOverrideService.cpp index 5fb94621bd30..b6968930b003 100644 --- a/security/manager/ssl/src/nsCertOverrideService.cpp +++ b/security/manager/ssl/src/nsCertOverrideService.cpp @@ -297,7 +297,7 @@ WriteEntryCallback(nsCertOverrideEntry *aEntry, nsIOutputStream *rawStreamPtr = (nsIOutputStream *)aArg; - nsresult rv; + PRUint32 unused; if (rawStreamPtr && aEntry) { @@ -309,19 +309,19 @@ WriteEntryCallback(nsCertOverrideEntry *aEntry, nsCertOverride::convertBitsToString(settings.mOverrideBits, bits_string); - rawStreamPtr->Write(aEntry->mHostWithPort.get(), aEntry->mHostWithPort.Length(), &rv); - rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &rv); + rawStreamPtr->Write(aEntry->mHostWithPort.get(), aEntry->mHostWithPort.Length(), &unused); + rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &unused); rawStreamPtr->Write(settings.mFingerprintAlgOID.get(), - settings.mFingerprintAlgOID.Length(), &rv); - rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &rv); + settings.mFingerprintAlgOID.Length(), &unused); + rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &unused); rawStreamPtr->Write(settings.mFingerprint.get(), - settings.mFingerprint.Length(), &rv); - rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &rv); + settings.mFingerprint.Length(), &unused); + rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &unused); rawStreamPtr->Write(bits_string.get(), - bits_string.Length(), &rv); - rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &rv); - rawStreamPtr->Write(settings.mDBKey.get(), settings.mDBKey.Length(), &rv); - rawStreamPtr->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &rv); + bits_string.Length(), &unused); + rawStreamPtr->Write(kTab, sizeof(kTab) - 1, &unused); + rawStreamPtr->Write(settings.mDBKey.get(), settings.mDBKey.Length(), &unused); + rawStreamPtr->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &unused); } return PL_DHASH_NEXT; @@ -361,7 +361,8 @@ nsCertOverrideService::Write() /* see ::Read for file format */ - bufferedOutputStream->Write(kHeader, sizeof(kHeader) - 1, &rv); + PRUint32 unused; + bufferedOutputStream->Write(kHeader, sizeof(kHeader) - 1, &unused); nsIOutputStream *rawStreamPtr = bufferedOutputStream; mSettingsTable.EnumerateEntries(WriteEntryCallback, rawStreamPtr); diff --git a/testing/marionette/atoms/atoms.js b/testing/marionette/atoms/atoms.js index ef8cf6cc67d1..a374cfd88682 100644 --- a/testing/marionette/atoms/atoms.js +++ b/testing/marionette/atoms/atoms.js @@ -225,82 +225,3 @@ var p={7:"NoSuchElementError",8:"NoSuchFrameError",9:"UnknownCommandError",10:"S o.prototype.toString=function(){return"["+this.name+"] "+this.message};function q(a){this.stack=Error().stack||"";a&&(this.message=""+a)}h(q,Error);q.prototype.name="CustomError";function r(a,b){b.unshift(a);q.call(this,i.apply(null,b));b.shift()}h(r,q);r.prototype.name="AssertionError";if(!n["1.9.1"]){for(var s=0,t=(""+k).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),u="1.9.1".replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),v=Math.max(t.length,u.length),w=0;0==s&&w(0==C[1].length? 0:parseInt(C[1],10))?1:0)||((0==B[2].length)<(0==C[2].length)?-1:(0==B[2].length)>(0==C[2].length)?1:0)||(B[2]C[2]?1:0)}while(0==s)}n["1.9.1"]=0<=s};var D={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},E={IMG:" ",BR:"\n"};function F(a,b,c){if(!(a.nodeName in D))if(3==a.nodeType)c?b.push((""+a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in E)b.push(E[a.nodeName]);else for(a=a.firstChild;a;)F(a,b,c),a=a.nextSibling};(function(){var a=g.Components;if(!a)return f;try{if(!a.classes)return f}catch(b){return f}var c=a.classes,a=a.interfaces;c["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator);c["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo);return!0})();function G(a,b,c,d,e){this.b=!!b;if(a&&(this.a=a))this.c="number"==typeof d?d:1!=this.a.nodeType?0:this.b?-1:1;this.depth=void 0!=e?e:this.c||0;this.b&&(this.depth*=-1)}h(G,function(){});G.prototype.a=null;G.prototype.c=0;h(function(a,b,c,d){G.call(this,a,b,0,null,d)},G);function H(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}function I(a){return H(a,"OPTION")?!0:H(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):f}var J={"class":"className",readonly:"readOnly"},K=["checked","disabled","draggable","hidden"];function L(a){if(I(a)){if(!I(a))throw new o(15,"Element is not selectable");var b="selected",c=a.type&&a.type.toLowerCase();if("checkbox"==c||"radio"==c)b="checked";var c=b,d=J[c]||c,b=a[d],e;if(e=void 0===b){b:if("string"==typeof K)d="string"!=typeof d||1!=d.length?-1:K.indexOf(d,0);else{for(e=0;e")&&(a=a.replace(ma,">"));-1!=a.indexOf('"')&&(a=a.replace(na,"""));return a}var ka=/&/g,la=//g,na=/\"/g,ja=/[&<>\"]/; -function oa(a,b){for(var c=0,d=ha(""+a).split("."),e=ha(""+b).split("."),f=Math.max(d.length,e.length),j=0;0==c&&j(0==w[1].length?0:parseInt(w[1],10))?1:0)||((0==v[2].length)<(0==w[2].length)?-1:(0== -v[2].length)>(0==w[2].length)?1:0)||(v[2]w[2]?1:0)}while(0==c)}return c}var pa=2147483648*Math.random()|0,qa={};function ra(a){return qa[a]||(qa[a]=(""+a).replace(/\-([a-z])/g,function(a,c){return c.toUpperCase()}))};var sa,ta;function ua(){return q.navigator?q.navigator.userAgent:k}var va,wa=q.navigator;va=wa&&wa.platform||"";sa=-1!=va.indexOf("Mac");ta=-1!=va.indexOf("Win");var xa=-1!=va.indexOf("Linux"),ya,za="",Aa=/rv\:([^\);]+)(\)|;)/.exec(ua());ya=za=Aa?Aa[1]:"";var Ba={};var Ca=window;function Da(a,b){for(var c in a)b.call(h,a[c],c,a)}function Ea(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b};function y(a,b){this.code=a;this.message=b||"";this.name=Fa[a]||Fa[13];var c=Error(this.message);c.name=this.name;this.stack=c.stack||""}x(y,Error); -var Fa={7:"NoSuchElementError",8:"NoSuchFrameError",9:"UnknownCommandError",10:"StaleElementReferenceError",11:"ElementNotVisibleError",12:"InvalidElementStateError",13:"UnknownError",15:"ElementNotSelectableError",19:"XPathLookupError",23:"NoSuchWindowError",24:"InvalidCookieDomainError",25:"UnableToSetCookieError",26:"ModalDialogOpenedError",27:"NoModalDialogOpenError",28:"ScriptTimeoutError",32:"InvalidSelectorError",33:"SqlDatabaseError",34:"MoveTargetOutOfBoundsError"}; -y.prototype.toString=function(){return"["+this.name+"] "+this.message};function Ga(a){this.stack=Error().stack||"";a&&(this.message=""+a)}x(Ga,Error);Ga.prototype.name="CustomError";function Ha(a,b){b.unshift(a);Ga.call(this,ga.apply(k,b));b.shift()}x(Ha,Ga);Ha.prototype.name="AssertionError";function Ia(a,b,c){if(!a){var d=Array.prototype.slice.call(arguments,2),e="Assertion failed";if(b)var e=e+(": "+b),f=d;g(new Ha(""+e,f||[]))}}function Ja(a,b){g(new Ha("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1)))};function z(a){return a[a.length-1]}var Ka=Array.prototype;function A(a,b){if(t(a))return!t(b)||1!=b.length?-1:a.indexOf(b,0);for(var c=0;cc?k:t(a)?a.charAt(c):a[c]}function Qa(a){return Ka.concat.apply(Ka,arguments)} -function Ra(a){if("array"==aa(a))return Qa(a);for(var b=[],c=0,d=a.length;c=arguments.length?Ka.slice.call(a,b):Ka.slice.call(a,b,c)};var Ta;Ba["1.9.1"]||(Ba["1.9.1"]=0<=oa(ya,"1.9.1"));function Ua(a,b){var c;c=(c=a.className)&&"function"==typeof c.split?c.split(/\s+/):[];var d=Sa(arguments,1),e;e=c;for(var f=0,j=0;j=a.length&&g(I);if(b in a)return a[b++];b++}};return c}g(Error("Not implemented"))};function K(a,b,c,d,e){this.p=!!b;a&&L(this,a,d);this.depth=e!=h?e:this.s||0;this.p&&(this.depth*=-1);this.Ca=!c}x(K,J);p=K.prototype;p.r=k;p.s=0;p.ma=l;function L(a,b,c,d){if(a.r=b)a.s="number"==typeof c?c:1!=a.r.nodeType?0:a.p?-1:1;"number"==typeof d&&(a.depth=d)} -p.next=function(){var a;if(this.ma){(!this.r||this.Ca&&0==this.depth)&&g(I);a=this.r;var b=this.p?-1:1;if(this.s==b){var c=this.p?a.lastChild:a.firstChild;c?L(this,c):L(this,a,-1*b)}else(c=this.p?a.previousSibling:a.nextSibling)?L(this,c):L(this,a.parentNode,-1*b);this.depth+=this.s*(this.p?-1:1)}else this.ma=i;(a=this.r)||g(I);return a}; -p.splice=function(a){var b=this.r,c=this.p?1:-1;this.s==c&&(this.s=-1*c,this.depth+=this.s*(this.p?-1:1));this.p=!this.p;K.prototype.next.call(this);this.p=!this.p;for(var c=ba(arguments[0])?arguments[0]:arguments,d=c.length-1;0<=d;d--)b.parentNode&&b.parentNode.insertBefore(c[d],b.nextSibling);bb(b)};function tb(a,b,c,d){K.call(this,a,b,c,k,d)}x(tb,K);tb.prototype.next=function(){do tb.aa.next.call(this);while(-1==this.s);return this.r};function ub(a,b){var c=D(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,k))?c[b]||c.getPropertyValue(b):""}function vb(a,b){return ub(a,b)||(a.currentStyle?a.currentStyle[b]:k)||a.style&&a.style[b]} -function wb(a){for(var b=D(a),c=vb(a,"position"),d="fixed"==c||"absolute"==c,a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=vb(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return k} -function xb(a){var b=new B;if(1==a.nodeType)if(a.getBoundingClientRect)a=a.getBoundingClientRect(),b.x=a.left,b.y=a.top;else{var c=mb(Wa(a));var d,e=D(a),f=vb(a,"position"),j=e.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==f&&(d=e.getBoxObjectFor(a))&&(0>d.screenX||0>d.screenY),f=new B(0,0),m=(e?9==e.nodeType?e:D(e):document).documentElement;if(a!=m)if(a.getBoundingClientRect)d=a.getBoundingClientRect(),a=mb(Wa(e)),f.x=d.left+a.x,f.y=d.top+a.y;else if(e.getBoxObjectFor&&!j)d=e.getBoxObjectFor(a), -a=e.getBoxObjectFor(m),f.x=d.screenX-a.screenX,f.y=d.screenY-a.screenY;else{d=a;do f.x+=d.offsetLeft,f.y+=d.offsetTop,d!=a&&(f.x+=d.clientLeft||0,f.y+=d.clientTop||0),d=d.offsetParent;while(d&&d!=a);for(d=a;(d=wb(d))&&d!=e.body&&d!=m;)f.x-=d.scrollLeft,f.y-=d.scrollTop}b.x=f.x-c.x;b.y=f.y-c.y}else c=u(a.ta),d=a,a.targetTouches?d=a.targetTouches[0]:c&&a.ta().targetTouches&&(d=a.ta().targetTouches[0]),b.x=d.clientX,b.y=d.clientY;return b} -function yb(a){var b=a.offsetWidth,c=a.offsetHeight;return!s(b)&&a.getBoundingClientRect?(a=a.getBoundingClientRect(),new Va(a.right-a.left,a.bottom-a.top)):new Va(b,c)};function M(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}var zb={"class":"className",readonly:"readOnly"},Ab=["checked","disabled","draggable","hidden"];function Bb(a,b){var c=zb[b]||b,d=a[c];if(!s(d)&&0<=A(Ab,c))return l;if(c="value"==b)if(c=M(a,"OPTION")){var e;c=b.toLowerCase();if(a.hasAttribute)e=a.hasAttribute(c);else try{e=a.attributes[c].specified}catch(f){e=l}c=!e}c&&(d=[],kb(a,d,l),d=d.join(""));return d} -var Cb="async,autofocus,autoplay,checked,compact,complete,controls,declare,defaultchecked,defaultselected,defer,disabled,draggable,ended,formnovalidate,hidden,indeterminate,iscontenteditable,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,paused,pubdate,readonly,required,reversed,scoped,seamless,seeking,selected,spellcheck,truespeed,willvalidate".split(","),Db="BUTTON,INPUT,OPTGROUP,OPTION,SELECT,TEXTAREA".split(","); -function Eb(a){var b=a.tagName.toUpperCase();return!(0<=A(Db,b))?i:Bb(a,"disabled")?l:a.parentNode&&1==a.parentNode.nodeType&&"OPTGROUP"==b||"OPTION"==b?Eb(a.parentNode):i}var Fb="text,search,tel,url,email,password,number".split(",");function Gb(a){return M(a,"TEXTAREA")?i:M(a,"INPUT")?0<=A(Fb,a.type.toLowerCase()):Hb(a)?i:l} -function Hb(a){function b(a){return"inherit"==a.contentEditable?(a=Ib(a))?b(a):l:"true"==a.contentEditable}return!s(a.contentEditable)?l:s(a.isContentEditable)?a.isContentEditable:b(a)}function Ib(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return M(a)?a:k}function Jb(a,b){b=ra(b);return ub(a,b)||Kb(a,b)} -function Kb(a,b){var c=a.currentStyle||a.style,d=c[b];!s(d)&&u(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?s(d)?d:k:(c=Ib(a))?Kb(c,b):k}function Lb(a){if(u(a.getBBox))try{var b=a.getBBox();if(b)return b}catch(c){}if("none"!=vb(a,"display"))a=yb(a);else{var b=a.style,d=b.display,e=b.visibility,f=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";a=yb(a);b.display=d;b.position=f;b.visibility=e}return a} -function N(a,b){function c(a){if("none"==Jb(a,"display"))return l;a=Ib(a);return!a||c(a)}function d(a){var b=Lb(a);return 0=c.length&&g(I);var j=c[b++];return a?j:d[":"+j]}};return j};function lc(a){this.l=new jc;a&&this.ca(a)}function mc(a){var b=typeof a;return"object"==b&&a||"function"==b?"o"+(a[da]||(a[da]=++ea)):b.substr(0,1)+a}p=lc.prototype;p.add=function(a){this.l.set(mc(a),a)};p.ca=function(a){for(var a=ic(a),b=a.length,c=0;c");S(191,"/","?");S(192,"`","~");S(219,"[","{");S(220,"\\","|");S(221,"]","}"); -S({c:59,e:186,opera:59},";",":");S(222,"'",'"');var yc=[sc,rc,vc,T];nc.prototype.m=function(a){return this.ka.contains(a)};function zc(a,b){a.m(b)&&0<=A(yc,b)&&g(new y(13,"Cannot press a modifier key that is already pressed."));var c=b.code!==k&&Ac(a,ec,b);if((!Bc(b)||Ac(a,Vb,b,!c))&&c&&a.ga&&!b.C)switch(b){case tc:case uc:var c=a.q(),d=0;hc(c)&&(d=c.selectionStart);c=d;b==tc?gc(a.q(),c-1):gc(a.q(),c+1)}a.ka.add(b)} -function Bc(a){if(a.C||a==qc)return i;switch(a){case T:case rc:case sc:return l;case vc:case wc:case xc:return i;default:return i}}function Cc(a,b){a.m(b)||g(new y(13,"Cannot release a key that is not pressed."));b.code===k||Ac(a,fc,b);a.ka.remove(b)} -function Ac(a,b,c,d){c.code===k&&g(new y(13,"Key must have a keycode to be fired."));var e=a.m(sc),f=a.m(rc),j=a.m(vc),m=a.m(T),r=c.code;c.C&&b==Vb?(c.C||g(new y(13,"not a character key")),c=(a.m(T)?c.Ja:c.C).charCodeAt(0)):c=0;return Rb(a.v,b,{altKey:e,ctrlKey:f,metaKey:j,shiftKey:m,keyCode:r,charCode:c,preventDefault:!!d})} -function Dc(a,b){Nb(a,b);a.ga=Gb(b)&&!Bb(b,"readOnly");var c;c=a.xa||a.v;var d=D(c).activeElement;if(c==d)c=l;else{if(d&&u(d.blur))try{d.blur()}catch(e){g(e)}u(c.focus)?(c.focus(),c=i):c=l}a.ga&&c&&gc(b,b.value.length)};function Ec(a){return Fc(a||arguments.callee.caller,[])} -function Fc(a,b){var c=[];if(0<=A(b,a))c.push("[...circular reference...]");else if(a&&50>b.length){c.push(Gc(a)+"(");for(var d=a.arguments,e=0;e=Nc(this).value){a=this.Ea(a,b,c);b="log:"+a.Ha;q.console&&(q.console.timeStamp?q.console.timeStamp(b):q.console.markTimeline&&q.console.markTimeline(b));q.msWriteProfilerMark&&q.msWriteProfilerMark(b);for(b=this;b;){var c=b,d=a;if(c.va)for(var e=0,f=h;f=c.va[e];e++)f(d);b=b.getParent()}}}; -U.prototype.Ea=function(a,b,c){var d=new Ic(a,""+b,this.Ia);if(c){d.sa=c;var e;var f=arguments.callee.caller;try{var j;var m;c:{for(var r=["window","location","href"],O=q,G;G=r.shift();)if(O[G]!=k)O=O[G];else{m=k;break c}m=O}if(t(c))j={message:c,name:"Unknown error",lineNumber:"Not available",fileName:m,stack:"Not available"};else{var v,w,r=l;try{v=c.lineNumber||c.Pa||"Not available"}catch(Ed){v="Not available",r=i}try{w=c.fileName||c.filename||c.sourceURL||m}catch(Fd){w="Not available",r=i}j=r|| -!c.lineNumber||!c.fileName||!c.stack?{message:c.message,name:c.name,lineNumber:v,fileName:w,stack:c.stack||"Not available"}:c}e="Message: "+ia(j.message)+'\nUrl: '+j.fileName+"\nLine: "+j.lineNumber+"\n\nBrowser stack:\n"+ia(j.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+ia(Ec(f)+"-> ")}catch(Cd){e="Exception trying to expose exception! You win, we lose. "+Cd}d.ra=e}return d};var Oc={},Pc=k; -function Qc(a){Pc||(Pc=new U(""),Oc[""]=Pc,Pc.ya(Mc));var b;if(!(b=Oc[a])){b=new U(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=Qc(a.substr(0,c));c.da||(c.da={});c.da[d]=b;b.Z=c;Oc[a]=b}return b};function Rc(){}x(Rc,function(){});Qc("goog.dom.SavedRange");x(function(a){this.La="goog_"+pa++;this.Da="goog_"+pa++;this.pa=Wa(a.ha());a.T(this.pa.fa("SPAN",{id:this.La}),this.pa.fa("SPAN",{id:this.Da}))},Rc);function V(){}function Sc(a){if(a.getSelection)return a.getSelection();var a=a.document,b=a.selection;if(b){try{var c=b.createRange();if(c.parentElement){if(c.parentElement().document!=a)return k}else if(!c.length||c.item(0).document!=a)return k}catch(d){return k}return b}return k}function Tc(a){for(var b=[],c=0,d=a.G();c=this.n(d,1,0):0<=this.n(d,0,0)&&0>=this.n(d,1,1)}catch(e){g(e)}};Yc.prototype.containsNode=function(a,b){return this.z(Vc(a),b)};Yc.prototype.t=function(){return new Xc(this.b(),this.j(),this.g(),this.k())};function Zc(a){this.a=a}x(Zc,Yc);p=Zc.prototype;p.F=function(){return this.a.commonAncestorContainer};p.b=function(){return this.a.startContainer};p.j=function(){return this.a.startOffset};p.g=function(){return this.a.endContainer};p.k=function(){return this.a.endOffset};p.n=function(a,b,c){return this.a.compareBoundaryPoints(1==c?1==b?q.Range.START_TO_START:q.Range.START_TO_END:1==b?q.Range.END_TO_START:q.Range.END_TO_END,a)};p.isCollapsed=function(){return this.a.collapsed}; -p.select=function(a){this.$(E(D(this.b())).getSelection(),a)};p.$=function(a){a.removeAllRanges();a.addRange(this.a)};p.insertNode=function(a,b){var c=this.a.cloneRange();c.collapse(b);c.insertNode(a);c.detach();return a}; -p.T=function(a,b){var c=E(D(this.b()));if(c=(c=Sc(c||window))&&$c(c))var d=c.b(),e=c.g(),f=c.j(),j=c.k();var m=this.a.cloneRange(),r=this.a.cloneRange();m.collapse(l);r.collapse(i);m.insertNode(b);r.insertNode(a);m.detach();r.detach();if(c){if(d.nodeType==C)for(;f>d.length;){f-=d.length;do d=d.nextSibling;while(d==a||d==b)}if(e.nodeType==C)for(;j>e.length;){j-=e.length;do e=e.nextSibling;while(e==a||e==b)}c=new ad;c.I=bd(d,f,e,j);"BR"==d.tagName&&(m=d.parentNode,f=A(m.childNodes,d),d=m);"BR"==e.tagName&& -(m=e.parentNode,j=A(m.childNodes,e),e=m);c.I?(c.f=e,c.i=j,c.d=d,c.h=f):(c.f=d,c.i=f,c.d=e,c.h=j);c.select()}};p.collapse=function(a){this.a.collapse(a)};function cd(a){this.a=a}x(cd,Zc);function Vc(a){var b=D(a).createRange();if(a.nodeType==C)b.setStart(a,0),b.setEnd(a,a.length);else if(X(a)){for(var c,d=a;(c=d.firstChild)&&X(c);)d=c;b.setStart(d,0);for(d=a;(c=d.lastChild)&&X(c);)d=c;b.setEnd(d,1==d.nodeType?d.childNodes.length:d.length)}else c=a.parentNode,a=A(c.childNodes,a),b.setStart(c,a),b.setEnd(c,a+1);return new cd(b)} -cd.prototype.$=function(a,b){var c=b?this.g():this.b(),d=b?this.k():this.j(),e=b?this.b():this.g(),f=b?this.j():this.k();a.collapse(c,d);(c!=e||d!=f)&&a.extend(e,f)};function dd(a){this.a=a}x(dd,Yc);Qc("goog.dom.browserrange.IeRange");function ed(a){var b=D(a).body.createTextRange();if(1==a.nodeType)b.moveToElementText(a),X(a)&&!a.childNodes.length&&b.collapse(l);else{for(var c=0,d=a;d=d.previousSibling;){var e=d.nodeType;if(e==C)c+=d.length;else if(1==e){b.moveToElementText(d);break}}d||b.moveToElementText(a.parentNode);b.collapse(!d);c&&b.move("character",c);b.moveEnd("character",a.length)}return b}p=dd.prototype;p.Q=k;p.f=k;p.d=k;p.i=-1;p.h=-1; -p.u=function(){this.Q=this.f=this.d=k;this.i=this.h=-1}; -p.F=function(){if(!this.Q){var a=this.a.text,b=this.a.duplicate(),c=a.replace(/ +$/,"");(c=a.length-c.length)&&b.moveEnd("character",-c);c=b.parentElement();b=b.htmlText.replace(/(\r\n|\r|\n)+/g," ").length;if(this.isCollapsed()&&0c.outerHTML.replace(/(\r\n|\r|\n)+/g," ").length;)c=c.parentNode;for(;1==c.childNodes.length&&c.innerText==(c.firstChild.nodeType==C?c.firstChild.nodeValue:c.firstChild.innerText)&&X(c.firstChild);)c=c.firstChild;0==a.length&&(c=fd(this,c));this.Q= -c}return this.Q};function fd(a,b){for(var c=b.childNodes,d=0,e=c.length;d=a.n(j,1,0):a.a.inRange(j))return fd(a,f)}}return b}p.b=function(){this.f||(this.f=gd(this,1),this.isCollapsed()&&(this.d=this.f));return this.f};p.j=function(){0>this.i&&(this.i=hd(this,1),this.isCollapsed()&&(this.h=this.i));return this.i}; -p.g=function(){if(this.isCollapsed())return this.b();this.d||(this.d=gd(this,0));return this.d};p.k=function(){if(this.isCollapsed())return this.j();0>this.h&&(this.h=hd(this,0),this.isCollapsed()&&(this.i=this.h));return this.h};p.n=function(a,b,c){return this.a.compareEndPoints((1==b?"Start":"End")+"To"+(1==c?"Start":"End"),a)}; -function gd(a,b,c){c=c||a.F();if(!c||!c.firstChild)return c;for(var d=1==b,e=0,f=c.childNodes.length;ea.n(G,1,0)&&0?|END~" + element.send_keys(numericShiftsEtc) + self.assertEqual(element.get_attribute("value"), numericShiftsEtc) + self.assertTrue(" up: 16" in result.text.strip()) + + def testLowerCaseAlphaKeys(self): + test_html = self.marionette.absolute_url("javascriptPage.html") + self.marionette.navigate(test_html) + + element = self.marionette.find_element("id", "keyReporter") + lowerAlphas = "abcdefghijklmnopqrstuvwxyz" + element.send_keys(lowerAlphas) + self.assertEqual(element.get_attribute("value"), lowerAlphas) + + def testUppercaseAlphaKeys(self): + test_html = self.marionette.absolute_url("javascriptPage.html") + self.marionette.navigate(test_html) + + result = self.marionette.find_element("id", "result") + element = self.marionette.find_element("id", "keyReporter") + upperAlphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + element.send_keys(upperAlphas) + self.assertEqual(element.get_attribute("value"), upperAlphas) + self.assertTrue(" up: 16" in result.text.strip()) + + def testAllPrintableKeys(self): + test_html = self.marionette.absolute_url("javascriptPage.html") + self.marionette.navigate(test_html) + + result = self.marionette.find_element("id", "result") + element = self.marionette.find_element("id", "keyReporter") + allPrintable = "!\"#$%&'()*+,-./0123456789:<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + element.send_keys(allPrintable) + + self.assertTrue(element.get_attribute("value"), allPrintable) + self.assertTrue(" up: 16" in result.text.strip()) + + def testSpecialSpaceKeys(self): + test_html = self.marionette.absolute_url("javascriptPage.html") + self.marionette.navigate(test_html) + + element = self.marionette.find_element("id", "keyReporter") + element.send_keys("abcd" + Keys.SPACE + "fgh" + Keys.SPACE + "ij") + self.assertEqual(element.get_attribute("value"), "abcd fgh ij") + + def testShouldTypeAnInteger(self): + test_html = self.marionette.absolute_url("javascriptPage.html") + self.marionette.navigate(test_html) + + element = self.marionette.find_element("id", "keyReporter") + element.send_keys(1234) + self.assertEqual(element.get_attribute("value"), "1234") diff --git a/testing/marionette/client/marionette/www/javascriptPage.html b/testing/marionette/client/marionette/www/javascriptPage.html new file mode 100644 index 000000000000..83ef4943a688 --- /dev/null +++ b/testing/marionette/client/marionette/www/javascriptPage.html @@ -0,0 +1,273 @@ + + + + + Testing Javascript + + + + + +

Type Stuff

+ +
+ +
+ +
  +
+

 

+
+ +
+ +
+
+ Key Up:
+ Key Down:
+ Key Press:
+ Change:
+ + + + + + + + +
+
+ + + +
What's for dinner?
+ +
+

Click for the mouse down event

+

Here's some text

+
+ +
+

Click for the mouse up event

+
+ +
+

Click for the mouse click event

+
+ +
+ Clicking this causes a JS exception in the click handler +
+ +
+
+ + + + + + + + + +
+ +
+ +
+

+ + +

+
+
+ + + +
+

Displayed

+ +
+ + + + + + + +
+ + + Check box you can't see + +
+ + +
+ +
+
+ + +
+
+ + +
+

This should be greenish

+
    +
  • So should this
  • +
  • But this is red
  • +
+
+ +Close window + +
+

I should be deleted when you click my containing div

+

Whereas, I should not

+
+ +
+ Click to hide me. +
+ +
+ Click actions delayed by 3000ms: +
+ Click to show black box +
+ +
+
+ +Click me to open a new window + +Mouse over me will throw a JS error + +
+ + Click on me to show the related target + +
+ +
+
+ +
+
+ + + + + diff --git a/testing/marionette/jar.mn b/testing/marionette/jar.mn index 1c287732ea07..50fbae26aabd 100644 --- a/testing/marionette/jar.mn +++ b/testing/marionette/jar.mn @@ -7,6 +7,7 @@ marionette.jar: content/marionette-actors.js (marionette-actors.js) content/marionette-listener.js (marionette-listener.js) content/marionette-elements.js (marionette-elements.js) + content/marionette-sendkeys.js (marionette-sendkeys.js) content/marionette-log-obj.js (marionette-log-obj.js) content/marionette-simpletest.js (marionette-simpletest.js) content/marionette-perf.js (marionette-perf.js) diff --git a/testing/marionette/marionette-actors.js b/testing/marionette/marionette-actors.js index 7934147ace4f..b5cab5d6ec8e 100644 --- a/testing/marionette/marionette-actors.js +++ b/testing/marionette/marionette-actors.js @@ -1150,7 +1150,7 @@ MarionetteDriverActor.prototype = { try { let el = this.curBrowser.elementManager.getKnownElement(aRequest.element, this.getCurrentWindow()); el.focus(); - utils.sendString(aRequest.value, utils.window); + utils.sendString(aRequest.value.join(""), utils.window); this.sendOk(); } catch (e) { diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index 9070a92df1a8..ab38b515a7be 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -23,6 +23,7 @@ utils.window = content; loader.loadSubScript("chrome://marionette/content/EventUtils.js", utils); loader.loadSubScript("chrome://marionette/content/ChromeUtils.js", utils); loader.loadSubScript("chrome://marionette/content/atoms.js", utils); +loader.loadSubScript("chrome://marionette/content/marionette-sendkeys.js", utils); loader.loadSubScript("chrome://specialpowers/content/specialpowersAPI.js"); loader.loadSubScript("chrome://specialpowers/content/specialpowers.js"); @@ -659,7 +660,7 @@ function isElementSelected(msg) { function sendKeysToElement(msg) { try { let el = elementManager.getKnownElement(msg.json.element, curWindow); - utils.sendKeysToElement(el, msg.json.value); + utils.type(curWindow.document, el, msg.json.value.join(""), true); sendOk(); } catch (e) { diff --git a/testing/marionette/marionette-sendkeys.js b/testing/marionette/marionette-sendkeys.js new file mode 100644 index 000000000000..c14285657175 --- /dev/null +++ b/testing/marionette/marionette-sendkeys.js @@ -0,0 +1,383 @@ +/* + * Copyright 2007-2009 WebDriver committers + * Copyright 2007-2009 Google Inc. + * Portions copyright 2012 Software Freedom Conservancy + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +var type = function(doc, element, text, releaseModifiers, + opt_keysState) { + + var currentTextLength = element.value.length; + element.selectionStart = currentTextLength; + element.selectionEnd = currentTextLength; + + // For consistency between native and synthesized events, convert common + // escape sequences to their Key enum aliases. + text = text.replace(new RegExp('\b', 'g'), '\uE003'). // DOM_VK_BACK_SPACE + replace(/\t/g, '\uE004'). // DOM_VK_TAB + replace(/(\r\n|\n|\r)/g, '\uE006'); // DOM_VK_RETURN + + var controlKey = false; + var shiftKey = false; + var altKey = false; + var metaKey = false; + if (opt_keysState) { + controlKey = opt_keysState.control; + shiftKey = opt_keysState.shiftKey; + altKey = opt_keysState.alt; + metaKey = opt_keysState.meta; + } + + shiftCount = 0; + + var upper = text.toUpperCase(); + + for (var i = 0; i < text.length; i++) { + var c = text.charAt(i); + + // NULL key: reset modifier key states, and continue + + if (c == '\uE000') { + if (controlKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey = false, shiftKey, altKey, metaKey, false); + } + + if (shiftKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey = false, altKey, metaKey, false); + } + + if (altKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey, altKey = false, metaKey, false); + } + + if (metaKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey, altKey, metaKey = false, false); + } + + continue; + } + + // otherwise decode keyCode, charCode, modifiers ... + + var modifierEvent = ""; + var charCode = 0; + var keyCode = 0; + + if (c == '\uE001') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CANCEL; + } else if (c == '\uE002') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HELP; + } else if (c == '\uE003') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SPACE; + } else if (c == '\uE004') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB; + } else if (c == '\uE005') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLEAR; + } else if (c == '\uE006') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RETURN; + } else if (c == '\uE007') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ENTER; + } else if (c == '\uE008') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT; + shiftKey = !shiftKey; + modifierEvent = shiftKey ? "keydown" : "keyup"; + } else if (c == '\uE009') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL; + controlKey = !controlKey; + modifierEvent = controlKey ? "keydown" : "keyup"; + } else if (c == '\uE00A') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT; + altKey = !altKey; + modifierEvent = altKey ? "keydown" : "keyup"; + } else if (c == '\uE03D') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META; + metaKey = !metaKey; + modifierEvent = metaKey ? "keydown" : "keyup"; + } else if (c == '\uE00B') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAUSE; + } else if (c == '\uE00C') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ESCAPE; + } else if (c == '\uE00D') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SPACE; + keyCode = charCode = ' '.charCodeAt(0); // printable + } else if (c == '\uE00E') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_UP; + } else if (c == '\uE00F') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN; + } else if (c == '\uE010') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_END; + } else if (c == '\uE011') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HOME; + } else if (c == '\uE012') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_LEFT; + } else if (c == '\uE013') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_UP; + } else if (c == '\uE014') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RIGHT; + } else if (c == '\uE015') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DOWN; + } else if (c == '\uE016') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_INSERT; + } else if (c == '\uE017') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DELETE; + } else if (c == '\uE018') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEMICOLON; + charCode = ';'.charCodeAt(0); + } else if (c == '\uE019') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_EQUALS; + charCode = '='.charCodeAt(0); + } else if (c == '\uE01A') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD0; + charCode = '0'.charCodeAt(0); + } else if (c == '\uE01B') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD1; + charCode = '1'.charCodeAt(0); + } else if (c == '\uE01C') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD2; + charCode = '2'.charCodeAt(0); + } else if (c == '\uE01D') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD3; + charCode = '3'.charCodeAt(0); + } else if (c == '\uE01E') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD4; + charCode = '4'.charCodeAt(0); + } else if (c == '\uE01F') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD5; + charCode = '5'.charCodeAt(0); + } else if (c == '\uE020') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD6; + charCode = '6'.charCodeAt(0); + } else if (c == '\uE021') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD7; + charCode = '7'.charCodeAt(0); + } else if (c == '\uE022') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD8; + charCode = '8'.charCodeAt(0); + } else if (c == '\uE023') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD9; + charCode = '9'.charCodeAt(0); + } else if (c == '\uE024') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_MULTIPLY; + charCode = '*'.charCodeAt(0); + } else if (c == '\uE025') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ADD; + charCode = '+'.charCodeAt(0); + } else if (c == '\uE026') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEPARATOR; + charCode = ','.charCodeAt(0); + } else if (c == '\uE027') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SUBTRACT; + charCode = '-'.charCodeAt(0); + } else if (c == '\uE028') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DECIMAL; + charCode = '.'.charCodeAt(0); + } else if (c == '\uE029') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DIVIDE; + charCode = '/'.charCodeAt(0); + } else if (c == '\uE031') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F1; + } else if (c == '\uE032') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F2; + } else if (c == '\uE033') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F3; + } else if (c == '\uE034') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F4; + } else if (c == '\uE035') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F5; + } else if (c == '\uE036') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F6; + } else if (c == '\uE037') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F7; + } else if (c == '\uE038') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F8; + } else if (c == '\uE039') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F9; + } else if (c == '\uE03A') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F10; + } else if (c == '\uE03B') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F11; + } else if (c == '\uE03C') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F12; + } else if (c == ',' || c == '<') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_COMMA; + charCode = c.charCodeAt(0); + } else if (c == '.' || c == '>') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PERIOD; + charCode = c.charCodeAt(0); + } else if (c == '/' || c == '?') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SLASH; + charCode = text.charCodeAt(i); + } else if (c == '`' || c == '~') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_QUOTE; + charCode = c.charCodeAt(0); + } else if (c == '{' || c == '[') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET; + charCode = c.charCodeAt(0); + } else if (c == '\\' || c == '|') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SLASH; + charCode = c.charCodeAt(0); + } else if (c == '}' || c == ']') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET; + charCode = c.charCodeAt(0); + } else if (c == '\'' || c == '"') { + keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_QUOTE; + charCode = c.charCodeAt(0); + } else { + keyCode = upper.charCodeAt(i); + charCode = text.charCodeAt(i); + } + + // generate modifier key event if needed, and continue + + if (modifierEvent) { + keyEvent(doc, element, modifierEvent, keyCode, 0, + controlKey, shiftKey, altKey, metaKey, false); + continue; + } + + // otherwise, shift down if needed + + var needsShift = false; + if (charCode) { + needsShift = /[A-Z\!\$\^\*\(\)\+\{\}\:\?\|~@#%&_"<>]/.test(c); + } + + if (needsShift && !shiftKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT; + keyEvent(doc, element, "keydown", kCode, 0, + controlKey, true, altKey, metaKey, false); + shiftCount += 1; + } + + // generate key[down/press/up] for key + + var pressCode = keyCode; + if (charCode >= 32 && charCode < 127) { + pressCode = 0; + if (!needsShift && shiftKey && charCode > 32) { + // If typing a lowercase character key and the shiftKey is down, the + // charCode should be mapped to the shifted key value. This assumes + // a default 104 international keyboard layout. + if (charCode >= 97 && charCode <= 122) { + charCode = charCode + 65 - 97; // [a-z] -> [A-Z] + } else { + var mapFrom = '`1234567890-=[]\\;\',./'; + var mapTo = '~!@#$%^&*()_+{}|:"<>?'; + + var value = String.fromCharCode(charCode). + replace(/([\[\\\.])/g, '\\$1'); + var index = mapFrom.search(value); + if (index >= 0) { + charCode = mapTo.charCodeAt(index); + } + } + } + } + + var accepted = + keyEvent(doc, element, "keydown", keyCode, 0, + controlKey, needsShift || shiftKey, altKey, metaKey, false); + + keyEvent(doc, element, "keypress", pressCode, charCode, + controlKey, needsShift || shiftKey, altKey, metaKey, !accepted); + + keyEvent(doc, element, "keyup", keyCode, 0, + controlKey, needsShift || shiftKey, altKey, metaKey, false); + + // shift up if needed + + if (needsShift && !shiftKey) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, false, altKey, metaKey, false); + } + } + + // exit cleanup: keyup active modifier keys + + if (controlKey && releaseModifiers) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey = false, shiftKey, altKey, metaKey, false); + } + + if (shiftKey && releaseModifiers) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey = false, altKey, metaKey, false); + } + + if (altKey && releaseModifiers) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey, altKey = false, metaKey, false); + } + + if (metaKey && releaseModifiers) { + var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META; + keyEvent(doc, element, "keyup", kCode, 0, + controlKey, shiftKey, altKey, metaKey = false, false); + } + + return { + shiftKey: shiftKey, + alt: altKey, + meta: metaKey, + control: controlKey + }; +}; + + +var keyEvent = function(doc, element, type, keyCode, charCode, + controlState, shiftState, altState, metaState, + shouldPreventDefault) { + var preventDefault = shouldPreventDefault == undefined ? false + : shouldPreventDefault; + + var keyboardEvent = doc.createEvent("KeyEvents"); + var currentView = doc.defaultView; + + keyboardEvent.initKeyEvent( + type, // in DOMString typeArg, + true, // in boolean canBubbleArg + true, // in boolean cancelableArg + currentView, // in nsIDOMAbstractView viewArg + controlState, // in boolean ctrlKeyArg + altState, // in boolean altKeyArg + shiftState, // in boolean shiftKeyArg + metaState, // in boolean metaKeyArg + keyCode, // in unsigned long keyCodeArg + charCode); // in unsigned long charCodeArg + + if (preventDefault) { + keyboardEvent.preventDefault(); + } + + var win = doc.defaultView; + var domUtil = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + return domUtil.dispatchDOMEventViaPresShell(element, keyboardEvent, true); +}; + diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index 0db8dfd4ac2c..76f56b479f0b 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -208,6 +208,12 @@ class MochitestOptions(optparse.OptionParser): "This directory will be deleted after the tests are finished") defaults["profilePath"] = tempfile.mkdtemp() + self.add_option("--testing-modules-dir", action = "store", + type = "string", dest = "testingModulesDir", + help = "Directory where testing-only JS modules are " + "located.") + defaults["testingModulesDir"] = None + self.add_option("--use-vmware-recording", action = "store_true", dest = "vmwareRecording", help = "enables recording while the application is running " @@ -324,6 +330,34 @@ See for details on the logg if options.webapprtContent and options.webapprtChrome: self.error("Only one of --webapprt-content and --webapprt-chrome may be given.") + # Try to guess the testing modules directory. + # This somewhat grotesque hack allows the buildbot machines to find the + # modules directory without having to configure the buildbot hosts. This + # code should never be executed in local runs because the build system + # should always set the flag that populates this variable. If buildbot ever + # passes this argument, this code can be deleted. + if options.testingModulesDir is None: + possible = os.path.join(os.getcwd(), os.path.pardir, 'modules') + + if os.path.isdir(possible): + options.testingModulesDir = possible + + # Even if buildbot is updated, we still want this, as the path we pass in + # to the app must be absolute and have proper slashes. + if options.testingModulesDir is not None: + options.testingModulesDir = os.path.normpath(options.testingModulesDir) + + if not os.path.isabs(options.testingModulesDir): + options.testingModulesDir = os.path.abspath(testingModulesDir) + + if not os.path.isdir(options.testingModulesDir): + self.error('--testing-modules-dir not a directory: %s' % + options.testingModulesDir) + + options.testingModulesDir = options.testingModulesDir.replace('\\', '/') + if options.testingModulesDir[-1] != '/': + options.testingModulesDir += '/' + return options @@ -806,6 +840,10 @@ toolbar#nav-bar { chrometestDir = "file:///" + chrometestDir.replace("\\", "/") manifestFile.write("content mochitests %s contentaccessible=yes\n" % chrometestDir) + if options.testingModulesDir is not None: + manifestFile.write("resource testing-common file:///%s\n" % + options.testingModulesDir) + # Call installChromeJar(). jarDir = "mochijar" if not os.path.isdir(os.path.join(self.SCRIPT_DIRECTORY, jarDir)): diff --git a/testing/mochitest/specialpowers/Makefile.in b/testing/mochitest/specialpowers/Makefile.in index fa11c095276e..3429696f5304 100644 --- a/testing/mochitest/specialpowers/Makefile.in +++ b/testing/mochitest/specialpowers/Makefile.in @@ -29,6 +29,10 @@ TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions include $(topsrcdir)/config/rules.mk +# JarMaker creates a chrome.manifest already, so the one from the source +# directory is not copied if it's not forced to be. +$(FINAL_TARGET)/chrome.manifest: FORCE + libs-preqs = \ $(call mkdir_deps,$(TEST_EXTENSIONS_DIR)) \ $(NULL) diff --git a/testing/testsuite-targets.mk b/testing/testsuite-targets.mk index 6513dfd3aa0e..1aa694e5a40b 100644 --- a/testing/testsuite-targets.mk +++ b/testing/testsuite-targets.mk @@ -28,25 +28,27 @@ TEST_PACKAGE_NAME := $(ANDROID_PACKAGE_NAME) endif RUN_MOCHITEST = \ - rm -f ./$@.log && \ - $(PYTHON) _tests/testing/mochitest/runtests.py --autorun --close-when-done \ - --console-level=INFO --log-file=./$@.log --file-level=INFO \ - --failure-file=$(call core_abspath,_tests/testing/mochitest/makefailures.json) \ - $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) + rm -f ./$@.log && \ + $(PYTHON) _tests/testing/mochitest/runtests.py --autorun --close-when-done \ + --console-level=INFO --log-file=./$@.log --file-level=INFO \ + --failure-file=$(call core_abspath,_tests/testing/mochitest/makefailures.json) \ + --testing-modules-dir=$(call core_abspath,_tests/modules) \ + $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) RERUN_MOCHITEST = \ - rm -f ./$@.log && \ - $(PYTHON) _tests/testing/mochitest/runtests.py --autorun --close-when-done \ - --console-level=INFO --log-file=./$@.log --file-level=INFO \ - --run-only-tests=makefailures.json \ - $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) + rm -f ./$@.log && \ + $(PYTHON) _tests/testing/mochitest/runtests.py --autorun --close-when-done \ + --console-level=INFO --log-file=./$@.log --file-level=INFO \ + --run-only-tests=makefailures.json \ + --testing-modules-dir=$(call core_abspath,_tests/modules) \ + $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) RUN_MOCHITEST_REMOTE = \ - rm -f ./$@.log && \ - $(PYTHON) _tests/testing/mochitest/runtestsremote.py --autorun --close-when-done \ - --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \ - --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \ - $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) + rm -f ./$@.log && \ + $(PYTHON) _tests/testing/mochitest/runtestsremote.py --autorun --close-when-done \ + --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \ + --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \ + $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) RUN_MOCHITEST_ROBOTIUM = \ rm -f ./$@.log && \ diff --git a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp index 88177df87333..587b990c36d4 100644 --- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp +++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp @@ -1115,7 +1115,7 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell, // view port. Move range forward to first visible point, // this speeds us up a lot in long documents nsFrameIterator frameTraversal(aPresContext, frame, - eLeaf, FrameIteratorFlags::FLAG_NONE); + eLeaf, nsFrameIterator::FLAG_NONE); while (rectVisibility == nsRectVisibility_kAboveViewport) { frameTraversal.Next(); diff --git a/toolkit/crashreporter/tools/symbolstore.py b/toolkit/crashreporter/tools/symbolstore.py index 94c70beffbb3..7ebce6d5bde6 100755 --- a/toolkit/crashreporter/tools/symbolstore.py +++ b/toolkit/crashreporter/tools/symbolstore.py @@ -248,13 +248,15 @@ class HGFileInfo(VCSFileInfo): if not srcdir in HGRepoInfo.repos: rev = read_output('hg', '-R', srcdir, 'parent', '--template={node|short}') - path = read_output('hg', '-R', srcdir, - 'showconfig', 'paths.default') - if path == '': - hg_root = os.environ.get("SRCSRV_ROOT") - if hg_root: - path = hg_root - else: + # Look for the default hg path. If SRVSRV_ROOT is set, we + # don't bother asking hg. + hg_root = os.environ.get("SRCSRV_ROOT") + if hg_root: + path = hg_root + else: + path = read_output('hg', '-R', srcdir, + 'showconfig', 'paths.default') + if not path: print >> sys.stderr, "Failed to get HG Repo for %s" % srcdir cleanroot = None if path != '': # not there? diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index ba545a820cdb..3141b2d2c06a 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -41,10 +41,6 @@ ifeq ($(OS_ARCH),OS2) CPPSRCS += dlldeps-xul.cpp endif -ifneq (,$(MOZ_ENABLE_GTK2)) -DEFINES += -DMOZ_ENABLE_GTK2 -endif - SHARED_LIBRARY_LIBS += \ $(DEPTH)/toolkit/xre/$(LIB_PREFIX)xulapp_s.$(LIB_SUFFIX) \ $(NULL) diff --git a/toolkit/library/nsStaticXULComponents.cpp b/toolkit/library/nsStaticXULComponents.cpp index 5d55de96d392..dea1e1e9def7 100644 --- a/toolkit/library/nsStaticXULComponents.cpp +++ b/toolkit/library/nsStaticXULComponents.cpp @@ -67,12 +67,7 @@ #endif #ifdef MOZ_PREF_EXTENSIONS -#ifdef MOZ_ENABLE_GTK -#define SYSTEMPREF_MODULES \ - MODULE(nsAutoConfigModule) -#else #define SYSTEMPREF_MODULES MODULE(nsAutoConfigModule) -#endif #else #define SYSTEMPREF_MODULES #endif @@ -125,7 +120,7 @@ #endif #ifdef MOZ_XUL -#ifdef MOZ_ENABLE_GTK +#ifdef MOZ_WIDGET_GTK #define UNIXPROXY_MODULE MODULE(nsUnixProxyModule) #endif #if defined(MOZ_WIDGET_QT) diff --git a/toolkit/webapps/WebappsInstaller.jsm b/toolkit/webapps/WebappsInstaller.jsm index 753558ea2de0..f53796d5624f 100644 --- a/toolkit/webapps/WebappsInstaller.jsm +++ b/toolkit/webapps/WebappsInstaller.jsm @@ -110,8 +110,6 @@ function NativeApp(aData) { this.appcacheDefined = (app.manifest.appcache_path != undefined); - this.manifest = app.manifest; - // The app registry is the Firefox profile from which the app // was installed. this.registryFolder = Services.dirsvc.get("ProfD", Ci.nsIFile); @@ -766,6 +764,41 @@ LinuxNativeApp.prototype = { } catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {} }, + /** + * Translate marketplace categories to freedesktop.org categories. + * + * @link http://standards.freedesktop.org/menu-spec/menu-spec-latest.html#category-registry + * + * @return an array of categories + */ + _translateCategories: function() { + let translations = { + "books-reference": "Education;Literature", + "business": "Finance", + "education": "Education", + "entertainment-sports": "Amusement;Sports", + "games": "Game", + "health-fitness": "MedicalSoftware", + "lifestyle": "Amusement", + "music": "Audio;Music", + "news-weather": "News", + "photos-media": "AudioVideo", + "productivity": "Office", + "shopping": "Amusement", + "social": "Chat", + "travel": "Amusement", + "utilities": "Utility" + }; + + // The trailing semicolon is needed as written in the freedesktop specification + let categories = ""; + for (let category of this.app.categories) { + categories += translations[category] + ";"; + } + + return categories; + }, + _createConfigFiles: function() { // ${InstallDir}/webapp.json writeToFile(this.configJson, JSON.stringify(this.webappJson), function() {}); @@ -790,6 +823,11 @@ LinuxNativeApp.prototype = { writer.setString("Desktop Entry", "Icon", this.iconFile.path); writer.setString("Desktop Entry", "Type", "Application"); writer.setString("Desktop Entry", "Terminal", "false"); + + let categories = this._translateCategories(); + if (categories) + writer.setString("Desktop Entry", "Categories", categories); + writer.writeFile(); }, diff --git a/webapprt/Makefile.in b/webapprt/Makefile.in index aad4a2556b35..a9907b4ad564 100644 --- a/webapprt/Makefile.in +++ b/webapprt/Makefile.in @@ -60,7 +60,7 @@ ifdef MOZILLA_OFFICIAL DEFINES += -DMOZILLA_OFFICIAL endif -libs:: +libs:: $(call mkdir_deps,$(FINAL_TARGET)) $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "resource webapprt ./" GRE_MILESTONE := $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt) diff --git a/widget/android/nsLookAndFeel.cpp b/widget/android/nsLookAndFeel.cpp index ded37230cb73..d1df152604d1 100644 --- a/widget/android/nsLookAndFeel.cpp +++ b/widget/android/nsLookAndFeel.cpp @@ -18,6 +18,8 @@ AndroidSystemColors nsLookAndFeel::mSystemColors; bool nsLookAndFeel::mInitializedShowPassword = false; bool nsLookAndFeel::mShowPassword = true; +static const PRUnichar UNICODE_BULLET = 0x2022; + nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel() { @@ -476,6 +478,14 @@ nsLookAndFeel::GetEchoPasswordImpl() PRUint32 nsLookAndFeel::GetPasswordMaskDelayImpl() { - // This value is hard-coded in PasswordTransformationMethod.java + // This value is hard-coded in Android OS's PasswordTransformationMethod.java return 1500; } + +/* virtual */ +PRUnichar +nsLookAndFeel::GetPasswordCharacterImpl() +{ + // This value is hard-coded in Android OS's PasswordTransformationMethod.java + return UNICODE_BULLET; +} diff --git a/widget/android/nsLookAndFeel.h b/widget/android/nsLookAndFeel.h index e8714ad35e37..61b2e8f3f0af 100644 --- a/widget/android/nsLookAndFeel.h +++ b/widget/android/nsLookAndFeel.h @@ -20,6 +20,7 @@ public: virtual bool GetFontImpl(FontID aID, nsString& aName, gfxFontStyle& aStyle); virtual bool GetEchoPasswordImpl(); virtual PRUint32 GetPasswordMaskDelayImpl(); + virtual PRUnichar GetPasswordCharacterImpl(); protected: static bool mInitializedSystemColors; diff --git a/widget/cocoa/nsFilePicker.mm b/widget/cocoa/nsFilePicker.mm index 17de5812f3e7..5f02f021f173 100644 --- a/widget/cocoa/nsFilePicker.mm +++ b/widget/cocoa/nsFilePicker.mm @@ -521,8 +521,7 @@ nsFilePicker::GetFilterList() NSMutableString* filterString = [[[NSMutableString alloc] initWithString: [NSString stringWithCharacters:filterWide.get() length:filterWide.Length()]] autorelease]; - NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString: - [NSString stringWithString:@". *"]]; + NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@". *"]; NSRange range = [filterString rangeOfCharacterFromSet:set]; while (range.length) { [filterString replaceCharactersInRange:range withString:@""]; diff --git a/widget/windows/nsWinGesture.cpp b/widget/windows/nsWinGesture.cpp index 312bdf28133e..eb3aa46788cf 100644 --- a/widget/windows/nsWinGesture.cpp +++ b/widget/windows/nsWinGesture.cpp @@ -12,14 +12,11 @@ #include "nsUXThemeData.h" #include "nsIDOMSimpleGestureEvent.h" #include "nsGUIEvent.h" +#include "mozilla/Constants.h" #include "mozilla/Preferences.h" using namespace mozilla; -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - #ifdef PR_LOGGING extern PRLogModuleInfo* gWindowsLog; #endif diff --git a/xpcom/base/nsConsoleService.cpp b/xpcom/base/nsConsoleService.cpp index 7c1e4ea0814b..311679d68b07 100644 --- a/xpcom/base/nsConsoleService.cpp +++ b/xpcom/base/nsConsoleService.cpp @@ -22,6 +22,9 @@ #if defined(ANDROID) #include #endif +#ifdef XP_WIN +#include +#endif using namespace mozilla; @@ -153,6 +156,14 @@ nsConsoleService::LogMessage(nsIConsoleMessage *message) NS_LossyConvertUTF16toASCII(msg).get()); } #endif +#ifdef XP_WIN + if (IsDebuggerPresent()) { + nsString msg; + message->GetMessageMoz(getter_Copies(msg)); + msg.AppendLiteral("\n"); + OutputDebugStringW(msg.get()); + } +#endif /* * If there's already a message in the slot we're about to replace, diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h index ef3d48f5c4c7..264caa80c058 100644 --- a/xpcom/build/BinaryPath.h +++ b/xpcom/build/BinaryPath.h @@ -76,7 +76,7 @@ private: return NS_ERROR_FAILURE; snprintf(aResult, MAXPATHLEN, "%s/%s", greHome, "dummy"); - aResult[MAXPATHLEN] = '\0'; + aResult[MAXPATHLEN-1] = '\0'; return NS_OK; }