Bug 946067 part 2. Generate Window's access checks in XPConnect based on WebIDL access annotations. r=bholley,peterv

This commit is contained in:
Boris Zbarsky 2013-12-09 10:34:03 -05:00
parent 1815e242b3
commit abefb320a5
3 changed files with 79 additions and 23 deletions

View File

@ -2510,6 +2510,47 @@ class CGClearCachedValueMethod(CGAbstractMethod):
% (declObj, noopRetval, saveMember, slotIndex, regetMember)
)).define()
class CGIsPermittedMethod(CGAbstractMethod):
"""
crossOriginGetters/Setters/Methods are sets of names of the relevant members.
"""
def __init__(self, descriptor, crossOriginGetters, crossOriginSetters,
crossOriginMethods):
self.crossOriginGetters = crossOriginGetters
self.crossOriginSetters = crossOriginSetters
self.crossOriginMethods = crossOriginMethods
args = [Argument("JSFlatString*", "prop"),
Argument("jschar", "propFirstChar"),
Argument("bool", "set")]
CGAbstractMethod.__init__(self, descriptor, "IsPermitted", "bool", args,
inline=True)
def definition_body(self):
allNames = self.crossOriginGetters | self.crossOriginSetters | self.crossOriginMethods
readwrite = self.crossOriginGetters & self.crossOriginSetters
readonly = (self.crossOriginGetters - self.crossOriginSetters) | self.crossOriginMethods
writeonly = self.crossOriginSetters - self.crossOriginGetters
cases = {}
for name in sorted(allNames):
cond = 'JS_FlatStringEqualsAscii(prop, "%s")' % name
if name in readonly:
cond = "!set && %s" % cond
elif name in writeonly:
cond = "set && %s" % cond
else:
assert name in readwrite
firstLetter = name[0]
case = cases.get(firstLetter, CGList([], "\n"))
case.append(CGGeneric("if (%s) {\n"
" return true;\n"
"}"% cond))
cases[firstLetter] = case
caseList = []
for firstLetter in sorted(cases.keys()):
caseList.append(CGCase("'%s'" % firstLetter, cases[firstLetter]))
switch = CGSwitch("propFirstChar", caseList)
return CGIndenter(CGList([switch, CGGeneric("return false;")], "\n\n")).define()
builtinNames = {
IDLType.Tags.bool: 'bool',
IDLType.Tags.int8: 'int8_t',
@ -8428,6 +8469,7 @@ class CGDescriptor(CGThing):
# method/getter/setter or jsonifier exist on the interface.
(hasMethod, hasGetter, hasLenientGetter, hasSetter, hasJsonifier,
hasLenientSetter) = False, False, False, False, False, False
crossOriginMethods, crossOriginGetters, crossOriginSetters = set(), set(), set()
for n in descriptor.interface.namedConstructors:
cgThings.append(CGClassConstructor(descriptor, n,
NamedConstructorName(n)))
@ -8446,6 +8488,8 @@ class CGDescriptor(CGThing):
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
if m.getExtendedAttribute("CrossOriginCallable"):
crossOriginMethods.add(m.identifier.name)
hasMethod = True
elif m.isAttr():
if m.isStatic():
@ -8456,6 +8500,8 @@ class CGDescriptor(CGThing):
if m.hasLenientThis():
hasLenientGetter = True
else:
if m.getExtendedAttribute("CrossOriginReadable"):
crossOriginGetters.add(m.identifier.name)
hasGetter = True
if not m.readonly:
if m.isStatic():
@ -8466,9 +8512,13 @@ class CGDescriptor(CGThing):
if m.hasLenientThis():
hasLenientSetter = True
else:
if m.getExtendedAttribute("CrossOriginWritable"):
crossOriginSetters.add(m.identifier.name)
hasSetter = True
elif m.getExtendedAttribute("PutForwards"):
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
if m.getExtendedAttribute("CrossOriginWritable"):
crossOriginSetters.add(m.identifier.name)
hasSetter = True
elif m.getExtendedAttribute("Replaceable"):
cgThings.append(CGSpecializedReplaceableSetter(descriptor, m))
@ -8617,6 +8667,14 @@ class CGDescriptor(CGThing):
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGGetConstructorObjectMethod(descriptor))
# See whether we need we need to generate an IsPermitted method
if (len(crossOriginGetters) or len(crossOriginSetters) or
len(crossOriginMethods)):
cgThings.append(CGIsPermittedMethod(descriptor,
crossOriginGetters,
crossOriginSetters,
crossOriginMethods))
cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n")
cgThings = CGWrapper(cgThings, pre='\n', post='\n')
self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),

View File

@ -26,11 +26,14 @@ typedef any Transferable;
[Global]
/*sealed*/ interface Window : EventTarget {
// the current browsing context
[Unforgeable, Throws] readonly attribute WindowProxy window;
[Replaceable, Throws] readonly attribute WindowProxy self;
[Unforgeable, Throws,
CrossOriginReadable] readonly attribute WindowProxy window;
[Replaceable, Throws,
CrossOriginReadable] readonly attribute WindowProxy self;
//[Unforgeable] readonly attribute Document? document;
[Throws] attribute DOMString name;
[PutForwards=href, Unforgeable, Throws] readonly attribute Location? location;
[PutForwards=href, Unforgeable, Throws,
CrossOriginReadable, CrossOriginWritable] readonly attribute Location? location;
[Throws] readonly attribute History history;
[Replaceable, Throws] readonly attribute BarProp locationbar;
[Replaceable, Throws] readonly attribute BarProp menubar;
@ -39,19 +42,19 @@ typedef any Transferable;
[Replaceable, Throws] readonly attribute BarProp statusbar;
[Replaceable, Throws] readonly attribute BarProp toolbar;
[Throws] attribute DOMString status;
[Throws] void close();
[Throws] readonly attribute boolean closed;
[Throws, CrossOriginCallable] void close();
[Throws, CrossOriginReadable] readonly attribute boolean closed;
[Throws] void stop();
[Throws] void focus();
[Throws] void blur();
[Throws, CrossOriginCallable] void focus();
[Throws, CrossOriginCallable] void blur();
// other browsing contexts
[Replaceable, Throws] readonly attribute WindowProxy frames;
[Replaceable] readonly attribute unsigned long length;
[Unforgeable, Throws] readonly attribute WindowProxy top;
[Throws] attribute WindowProxy? opener;
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
[Replaceable, CrossOriginReadable] readonly attribute unsigned long length;
[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy top;
[Throws, CrossOriginReadable] attribute WindowProxy? opener;
//[Throws] readonly attribute WindowProxy parent;
[Replaceable, Throws] readonly attribute WindowProxy? parent;
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy? parent;
[Throws] readonly attribute Element? frameElement;
//[Throws] WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank", optional DOMString features = "", optional boolean replace = false);
[Throws] WindowProxy? open(optional DOMString url = "", optional DOMString target = "", optional DOMString features = "");
@ -73,7 +76,7 @@ typedef any Transferable;
//[Throws] any showModalDialog(DOMString url, optional any argument);
[Throws] any showModalDialog(DOMString url, optional any argument, optional DOMString options = "");
[Throws] void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
[Throws, CrossOriginCallable] void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
// also has obsolete members
};

View File

@ -16,6 +16,7 @@
#include "jsfriendapi.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/WindowBinding.h"
using namespace mozilla;
using namespace JS;
@ -146,16 +147,10 @@ IsPermitted(const char *name, JSFlatString *prop, bool set)
NAME('L', "Location",
PROP('h', W("href"))
PROP('r', R("replace")))
NAME('W', "Window",
PROP('b', R("blur"))
PROP('c', R("close") R("closed"))
PROP('f', R("focus") R("frames"))
PROP('l', RW("location") R("length"))
PROP('o', R("opener"))
PROP('p', R("parent") R("postMessage"))
PROP('s', R("self"))
PROP('t', R("top"))
PROP('w', R("window")))
case 'W':
if (!strcmp(name, "Window"))
return dom::WindowBinding::IsPermitted(prop, propChars[0], set);
break;
}
return false;
}