Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | #!/usr/bin/env python |
michael@0 | 2 | # typelib.py - Generate XPCOM typelib files from IDL. |
michael@0 | 3 | # |
michael@0 | 4 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 7 | |
michael@0 | 8 | """Generate an XPIDL typelib for the IDL files specified on the command line""" |
michael@0 | 9 | |
michael@0 | 10 | import os |
michael@0 | 11 | import sys |
michael@0 | 12 | import xpidl, xpt |
michael@0 | 13 | |
michael@0 | 14 | # A map of xpidl.py types to xpt.py types |
michael@0 | 15 | TypeMap = { |
michael@0 | 16 | # nsresult is not strictly an xpidl.py type, but it's useful here |
michael@0 | 17 | 'nsresult': xpt.Type.Tags.uint32, |
michael@0 | 18 | # builtins |
michael@0 | 19 | 'boolean': xpt.Type.Tags.boolean, |
michael@0 | 20 | 'void': xpt.Type.Tags.void, |
michael@0 | 21 | 'int16_t': xpt.Type.Tags.int16, |
michael@0 | 22 | 'int32_t': xpt.Type.Tags.int32, |
michael@0 | 23 | 'int64_t': xpt.Type.Tags.int64, |
michael@0 | 24 | 'uint8_t': xpt.Type.Tags.uint8, |
michael@0 | 25 | 'uint16_t': xpt.Type.Tags.uint16, |
michael@0 | 26 | 'uint32_t': xpt.Type.Tags.uint32, |
michael@0 | 27 | 'uint64_t': xpt.Type.Tags.uint64, |
michael@0 | 28 | 'octet': xpt.Type.Tags.uint8, |
michael@0 | 29 | 'short': xpt.Type.Tags.int16, |
michael@0 | 30 | 'long': xpt.Type.Tags.int32, |
michael@0 | 31 | 'long long': xpt.Type.Tags.int64, |
michael@0 | 32 | 'unsigned short': xpt.Type.Tags.uint16, |
michael@0 | 33 | 'unsigned long': xpt.Type.Tags.uint32, |
michael@0 | 34 | 'unsigned long long': xpt.Type.Tags.uint64, |
michael@0 | 35 | 'float': xpt.Type.Tags.float, |
michael@0 | 36 | 'double': xpt.Type.Tags.double, |
michael@0 | 37 | 'char': xpt.Type.Tags.char, |
michael@0 | 38 | 'string': xpt.Type.Tags.char_ptr, |
michael@0 | 39 | 'wchar': xpt.Type.Tags.wchar_t, |
michael@0 | 40 | 'wstring': xpt.Type.Tags.wchar_t_ptr, |
michael@0 | 41 | # special types |
michael@0 | 42 | 'nsid': xpt.Type.Tags.nsIID, |
michael@0 | 43 | 'domstring': xpt.Type.Tags.DOMString, |
michael@0 | 44 | 'astring': xpt.Type.Tags.AString, |
michael@0 | 45 | 'utf8string': xpt.Type.Tags.UTF8String, |
michael@0 | 46 | 'cstring': xpt.Type.Tags.CString, |
michael@0 | 47 | 'jsval': xpt.Type.Tags.jsval |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | # XXXkhuey dipper types should go away (bug 677784) |
michael@0 | 51 | def isDipperType(type): |
michael@0 | 52 | return type == xpt.Type.Tags.DOMString or type == xpt.Type.Tags.AString or type == xpt.Type.Tags.CString or type == xpt.Type.Tags.UTF8String |
michael@0 | 53 | |
michael@0 | 54 | def build_interface(iface, ifaces): |
michael@0 | 55 | def get_type(type, calltype, iid_is=None, size_is=None): |
michael@0 | 56 | """ Return the appropriate xpt.Type object for this param """ |
michael@0 | 57 | |
michael@0 | 58 | while isinstance(type, xpidl.Typedef): |
michael@0 | 59 | type = type.realtype |
michael@0 | 60 | |
michael@0 | 61 | if isinstance(type, xpidl.Builtin): |
michael@0 | 62 | if type.name == 'string' and size_is != None: |
michael@0 | 63 | return xpt.StringWithSizeType(size_is, size_is) |
michael@0 | 64 | elif type.name == 'wstring' and size_is != None: |
michael@0 | 65 | return xpt.WideStringWithSizeType(size_is, size_is) |
michael@0 | 66 | else: |
michael@0 | 67 | tag = TypeMap[type.name] |
michael@0 | 68 | isPtr = (tag == xpt.Type.Tags.char_ptr or tag == xpt.Type.Tags.wchar_t_ptr) |
michael@0 | 69 | return xpt.SimpleType(tag, |
michael@0 | 70 | pointer=isPtr, |
michael@0 | 71 | reference=False) |
michael@0 | 72 | |
michael@0 | 73 | if isinstance(type, xpidl.Array): |
michael@0 | 74 | # NB: For an Array<T> we pass down the iid_is to get the type of T. |
michael@0 | 75 | # This allows Arrays of InterfaceIs types to work. |
michael@0 | 76 | return xpt.ArrayType(get_type(type.type, calltype, iid_is), size_is, |
michael@0 | 77 | #XXXkhuey length_is duplicates size_is (bug 677788), |
michael@0 | 78 | size_is) |
michael@0 | 79 | |
michael@0 | 80 | if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward): |
michael@0 | 81 | xptiface = None |
michael@0 | 82 | for i in ifaces: |
michael@0 | 83 | if i.name == type.name: |
michael@0 | 84 | xptiface = i |
michael@0 | 85 | |
michael@0 | 86 | if not xptiface: |
michael@0 | 87 | xptiface = xpt.Interface(name=type.name) |
michael@0 | 88 | ifaces.append(xptiface) |
michael@0 | 89 | |
michael@0 | 90 | return xpt.InterfaceType(xptiface) |
michael@0 | 91 | |
michael@0 | 92 | if isinstance(type, xpidl.Native): |
michael@0 | 93 | if type.specialtype: |
michael@0 | 94 | # XXXkhuey jsval is marked differently in the typelib and in the headers :-( |
michael@0 | 95 | isPtr = (type.isPtr(calltype) or type.isRef(calltype)) and not type.specialtype == 'jsval' |
michael@0 | 96 | isRef = type.isRef(calltype) and not type.specialtype == 'jsval' |
michael@0 | 97 | return xpt.SimpleType(TypeMap[type.specialtype], |
michael@0 | 98 | pointer=isPtr, |
michael@0 | 99 | reference=isRef) |
michael@0 | 100 | elif iid_is != None: |
michael@0 | 101 | return xpt.InterfaceIsType(iid_is) |
michael@0 | 102 | else: |
michael@0 | 103 | # void ptr |
michael@0 | 104 | return xpt.SimpleType(TypeMap['void'], |
michael@0 | 105 | pointer=True, |
michael@0 | 106 | reference=False) |
michael@0 | 107 | |
michael@0 | 108 | raise Exception("Unknown type!") |
michael@0 | 109 | |
michael@0 | 110 | def get_nsresult(): |
michael@0 | 111 | return xpt.SimpleType(TypeMap['nsresult']) |
michael@0 | 112 | |
michael@0 | 113 | def build_nsresult_param(): |
michael@0 | 114 | return xpt.Param(get_nsresult()) |
michael@0 | 115 | |
michael@0 | 116 | def get_result_type(m): |
michael@0 | 117 | if not m.notxpcom: |
michael@0 | 118 | return get_nsresult() |
michael@0 | 119 | |
michael@0 | 120 | return get_type(m.realtype, '') |
michael@0 | 121 | |
michael@0 | 122 | def build_result_param(m): |
michael@0 | 123 | return xpt.Param(get_result_type(m)) |
michael@0 | 124 | |
michael@0 | 125 | def build_retval_param(m): |
michael@0 | 126 | type = get_type(m.realtype, 'out') |
michael@0 | 127 | if isDipperType(type.tag): |
michael@0 | 128 | # NB: The retval bit needs to be set here, contrary to what the |
michael@0 | 129 | # xpt spec says. |
michael@0 | 130 | return xpt.Param(type, in_=True, retval=True, dipper=True) |
michael@0 | 131 | return xpt.Param(type, in_=False, out=True, retval=True) |
michael@0 | 132 | |
michael@0 | 133 | def build_attr_param(a, getter=False, setter=False): |
michael@0 | 134 | if not (getter or setter): |
michael@0 | 135 | raise Exception("Attribute param must be for a getter or a setter!") |
michael@0 | 136 | |
michael@0 | 137 | type = get_type(a.realtype, getter and 'out' or 'in') |
michael@0 | 138 | if setter: |
michael@0 | 139 | return xpt.Param(type) |
michael@0 | 140 | else: |
michael@0 | 141 | if isDipperType(type.tag): |
michael@0 | 142 | # NB: The retval bit needs to be set here, contrary to what the |
michael@0 | 143 | # xpt spec says. |
michael@0 | 144 | return xpt.Param(type, in_=True, retval=True, dipper=True) |
michael@0 | 145 | return xpt.Param(type, in_=False, out=True, retval=True) |
michael@0 | 146 | |
michael@0 | 147 | if iface.namemap is None: |
michael@0 | 148 | raise Exception("Interface was not resolved.") |
michael@0 | 149 | |
michael@0 | 150 | consts = [] |
michael@0 | 151 | methods = [] |
michael@0 | 152 | |
michael@0 | 153 | def build_const(c): |
michael@0 | 154 | consts.append(xpt.Constant(c.name, get_type(c.basetype, ''), c.getValue())) |
michael@0 | 155 | |
michael@0 | 156 | def build_method(m): |
michael@0 | 157 | params = [] |
michael@0 | 158 | |
michael@0 | 159 | def build_param(p): |
michael@0 | 160 | def findattr(p, attr): |
michael@0 | 161 | if hasattr(p, attr) and getattr(p, attr): |
michael@0 | 162 | for i, param in enumerate(m.params): |
michael@0 | 163 | if param.name == getattr(p, attr): |
michael@0 | 164 | return i |
michael@0 | 165 | return None |
michael@0 | 166 | |
michael@0 | 167 | iid_is = findattr(p, 'iid_is') |
michael@0 | 168 | size_is = findattr(p, 'size_is') |
michael@0 | 169 | |
michael@0 | 170 | in_ = p.paramtype.count("in") |
michael@0 | 171 | out = p.paramtype.count("out") |
michael@0 | 172 | dipper = False |
michael@0 | 173 | type = get_type(p.realtype, p.paramtype, iid_is=iid_is, size_is=size_is) |
michael@0 | 174 | if out and isDipperType(type.tag): |
michael@0 | 175 | out = False |
michael@0 | 176 | dipper = True |
michael@0 | 177 | |
michael@0 | 178 | return xpt.Param(type, in_, out, p.retval, p.shared, dipper, p.optional) |
michael@0 | 179 | |
michael@0 | 180 | for p in m.params: |
michael@0 | 181 | params.append(build_param(p)) |
michael@0 | 182 | |
michael@0 | 183 | if not m.notxpcom and m.realtype.name != 'void': |
michael@0 | 184 | params.append(build_retval_param(m)) |
michael@0 | 185 | |
michael@0 | 186 | methods.append(xpt.Method(m.name, build_result_param(m), params, |
michael@0 | 187 | getter=False, setter=False, notxpcom=m.notxpcom, |
michael@0 | 188 | constructor=False, hidden=m.noscript, |
michael@0 | 189 | optargc=m.optional_argc, |
michael@0 | 190 | implicit_jscontext=m.implicit_jscontext)) |
michael@0 | 191 | |
michael@0 | 192 | def build_attr(a): |
michael@0 | 193 | # Write the getter |
michael@0 | 194 | methods.append(xpt.Method(a.name, build_nsresult_param(), |
michael@0 | 195 | [build_attr_param(a, getter=True)], |
michael@0 | 196 | getter=True, setter=False, |
michael@0 | 197 | constructor=False, hidden=a.noscript, |
michael@0 | 198 | optargc=False, |
michael@0 | 199 | implicit_jscontext=a.implicit_jscontext)) |
michael@0 | 200 | |
michael@0 | 201 | # And maybe the setter |
michael@0 | 202 | if not a.readonly: |
michael@0 | 203 | methods.append(xpt.Method(a.name, build_nsresult_param(), |
michael@0 | 204 | [build_attr_param(a, setter=True)], |
michael@0 | 205 | getter=False, setter=True, |
michael@0 | 206 | constructor=False, hidden=a.noscript, |
michael@0 | 207 | optargc=False, |
michael@0 | 208 | implicit_jscontext=a.implicit_jscontext)) |
michael@0 | 209 | |
michael@0 | 210 | for member in iface.members: |
michael@0 | 211 | if isinstance(member, xpidl.ConstMember): |
michael@0 | 212 | build_const(member) |
michael@0 | 213 | elif isinstance(member, xpidl.Attribute): |
michael@0 | 214 | build_attr(member) |
michael@0 | 215 | elif isinstance(member, xpidl.Method): |
michael@0 | 216 | build_method(member) |
michael@0 | 217 | elif isinstance(member, xpidl.CDATA): |
michael@0 | 218 | pass |
michael@0 | 219 | else: |
michael@0 | 220 | raise Exception("Unexpected interface member: %s" % member) |
michael@0 | 221 | |
michael@0 | 222 | parent = None |
michael@0 | 223 | if iface.base: |
michael@0 | 224 | for i in ifaces: |
michael@0 | 225 | if i.name == iface.base: |
michael@0 | 226 | parent = i |
michael@0 | 227 | if not parent: |
michael@0 | 228 | parent = xpt.Interface(name=iface.base) |
michael@0 | 229 | ifaces.append(parent) |
michael@0 | 230 | |
michael@0 | 231 | return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods, |
michael@0 | 232 | constants=consts, resolved=True, parent=parent, |
michael@0 | 233 | scriptable=iface.attributes.scriptable, |
michael@0 | 234 | function=iface.attributes.function, |
michael@0 | 235 | builtinclass=iface.attributes.builtinclass) |
michael@0 | 236 | |
michael@0 | 237 | def write_typelib(idl, fd, filename): |
michael@0 | 238 | """ Generate the typelib. """ |
michael@0 | 239 | |
michael@0 | 240 | # We only care about interfaces |
michael@0 | 241 | ifaces = [] |
michael@0 | 242 | for p in idl.productions: |
michael@0 | 243 | if p.kind == 'interface': |
michael@0 | 244 | ifaces.append(build_interface(p, ifaces)) |
michael@0 | 245 | |
michael@0 | 246 | typelib = xpt.Typelib(interfaces=ifaces) |
michael@0 | 247 | typelib.writefd(fd) |
michael@0 | 248 | |
michael@0 | 249 | if __name__ == '__main__': |
michael@0 | 250 | from optparse import OptionParser |
michael@0 | 251 | o = OptionParser() |
michael@0 | 252 | o.add_option('-I', action='append', dest='incdirs', default=['.'], |
michael@0 | 253 | help="Directory to search for imported files") |
michael@0 | 254 | o.add_option('--cachedir', dest='cachedir', default=None, |
michael@0 | 255 | help="Directory in which to cache lex/parse tables.") |
michael@0 | 256 | o.add_option('-o', dest='outfile', default=None, |
michael@0 | 257 | help="Output file") |
michael@0 | 258 | o.add_option('-d', dest='depfile', default=None, |
michael@0 | 259 | help="Generate a make dependency file") |
michael@0 | 260 | o.add_option('--regen', action='store_true', dest='regen', default=False, |
michael@0 | 261 | help="Regenerate IDL Parser cache") |
michael@0 | 262 | options, args = o.parse_args() |
michael@0 | 263 | file = args[0] if args else None |
michael@0 | 264 | |
michael@0 | 265 | if options.cachedir is not None: |
michael@0 | 266 | if not os.path.isdir(options.cachedir): |
michael@0 | 267 | os.mkdir(options.cachedir) |
michael@0 | 268 | sys.path.append(options.cachedir) |
michael@0 | 269 | |
michael@0 | 270 | if options.regen: |
michael@0 | 271 | if options.cachedir is None: |
michael@0 | 272 | print >>sys.stderr, "--regen requires --cachedir" |
michael@0 | 273 | sys.exit(1) |
michael@0 | 274 | |
michael@0 | 275 | p = xpidl.IDLParser(outputdir=options.cachedir, regen=True) |
michael@0 | 276 | sys.exit(0) |
michael@0 | 277 | |
michael@0 | 278 | if options.depfile is not None and options.outfile is None: |
michael@0 | 279 | print >>sys.stderr, "-d requires -o" |
michael@0 | 280 | sys.exit(1) |
michael@0 | 281 | |
michael@0 | 282 | if options.outfile is not None: |
michael@0 | 283 | outfd = open(options.outfile, 'wb') |
michael@0 | 284 | closeoutfd = True |
michael@0 | 285 | else: |
michael@0 | 286 | raise "typelib generation requires an output file" |
michael@0 | 287 | |
michael@0 | 288 | p = xpidl.IDLParser(outputdir=options.cachedir) |
michael@0 | 289 | idl = p.parse(open(file).read(), filename=file) |
michael@0 | 290 | idl.resolve(options.incdirs, p) |
michael@0 | 291 | write_typelib(idl, outfd, file) |
michael@0 | 292 | |
michael@0 | 293 | if closeoutfd: |
michael@0 | 294 | outfd.close() |
michael@0 | 295 | |
michael@0 | 296 | if options.depfile is not None: |
michael@0 | 297 | depfd = open(options.depfile, 'w') |
michael@0 | 298 | deps = [dep.replace('\\', '/') for dep in idl.deps] |
michael@0 | 299 | |
michael@0 | 300 | print >>depfd, "%s: %s" % (options.outfile, " ".join(deps)) |
michael@0 | 301 | for dep in deps: |
michael@0 | 302 | print >>depfd, "%s:" % dep |