mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1756500
- Add [Trial="Name"] condition to WebIDL. r=peterv
Differential Revision: https://phabricator.services.mozilla.com/D139315
This commit is contained in:
parent
7852c208be
commit
93ce20c599
@ -3899,6 +3899,8 @@ class Document : public nsINode,
|
||||
public:
|
||||
bool IsThirdPartyForFlashClassifier();
|
||||
|
||||
const OriginTrials& Trials() const { return mTrials; }
|
||||
|
||||
private:
|
||||
void DoCacheAllKnownLangPrefs();
|
||||
void RecomputeLanguageFromCharset();
|
||||
|
@ -2402,13 +2402,20 @@ class MemberCondition:
|
||||
secureContext: A bool indicating whether a secure context is required.
|
||||
nonExposedGlobals: A set of names of globals. Can be empty, in which case
|
||||
it's treated the same way as None.
|
||||
trial: The name of the origin trial.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, pref=None, func=None, secureContext=False, nonExposedGlobals=None
|
||||
self,
|
||||
pref=None,
|
||||
func=None,
|
||||
secureContext=False,
|
||||
nonExposedGlobals=None,
|
||||
trial=None,
|
||||
):
|
||||
assert pref is None or isinstance(pref, str)
|
||||
assert func is None or isinstance(func, str)
|
||||
assert trial is None or isinstance(trial, str)
|
||||
assert isinstance(secureContext, bool)
|
||||
assert nonExposedGlobals is None or isinstance(nonExposedGlobals, set)
|
||||
self.pref = pref
|
||||
@ -2435,12 +2442,18 @@ class MemberCondition:
|
||||
else:
|
||||
self.nonExposedGlobals = "0"
|
||||
|
||||
if trial:
|
||||
self.trial = "OriginTrial::" + trial
|
||||
else:
|
||||
self.trial = "OriginTrial(0)"
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.pref == other.pref
|
||||
and self.func == other.func
|
||||
and self.secureContext == other.secureContext
|
||||
and self.nonExposedGlobals == other.nonExposedGlobals
|
||||
and self.trial == other.trial
|
||||
)
|
||||
|
||||
def __ne__(self, other):
|
||||
@ -2452,6 +2465,7 @@ class MemberCondition:
|
||||
or self.secureContext
|
||||
or self.func != "nullptr"
|
||||
or self.nonExposedGlobals != "0"
|
||||
or self.trial != "OriginTrial(0)"
|
||||
)
|
||||
|
||||
|
||||
@ -2513,11 +2527,19 @@ class PropertyDefiner:
|
||||
interface = descriptor.interface
|
||||
nonExposureSet = interface.exposureSet - interfaceMember.exposureSet
|
||||
|
||||
trial = PropertyDefiner.getStringAttr(interfaceMember, "Trial")
|
||||
if trial and interface.identifier.name in ["Window", "Document"]:
|
||||
raise TypeError(
|
||||
"[Trial] not yet supported for %s.%s, see bug 1757935"
|
||||
% (interface.identifier.name, interfaceMember.identifier.name)
|
||||
)
|
||||
|
||||
return MemberCondition(
|
||||
PropertyDefiner.getStringAttr(interfaceMember, "Pref"),
|
||||
PropertyDefiner.getStringAttr(interfaceMember, "Func"),
|
||||
interfaceMember.getExtendedAttribute("SecureContext") is not None,
|
||||
nonExposureSet,
|
||||
trial,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@ -2642,7 +2664,7 @@ class PropertyDefiner:
|
||||
disablersTemplate = dedent(
|
||||
"""
|
||||
static const PrefableDisablers %s_disablers%d = {
|
||||
%s, %s, %s, %s
|
||||
%s, %s, %s, %s, %s
|
||||
};
|
||||
"""
|
||||
)
|
||||
@ -2663,6 +2685,7 @@ class PropertyDefiner:
|
||||
len(specs),
|
||||
condition.prefFuncIndex,
|
||||
toStringBool(condition.secureContext),
|
||||
condition.trial,
|
||||
condition.nonExposedGlobals,
|
||||
condition.func,
|
||||
)
|
||||
@ -4094,6 +4117,13 @@ def getRawConditionList(idlobj, cxName, objName, ignoreSecureContext=False):
|
||||
if func:
|
||||
assert isinstance(func, list) and len(func) == 1
|
||||
conditions.append("%s(%s, %s)" % (func[0], cxName, objName))
|
||||
trial = idlobj.getExtendedAttribute("Trial")
|
||||
if trial:
|
||||
assert isinstance(trial, list) and len(trial) == 1
|
||||
conditions.append(
|
||||
"OriginTrials::IsEnabled(%s, %s, OriginTrial::%s)"
|
||||
% (cxName, objName, trial[0])
|
||||
)
|
||||
if not ignoreSecureContext and idlobj.getExtendedAttribute("SecureContext"):
|
||||
conditions.append(
|
||||
"mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(%s, %s)"
|
||||
@ -18328,40 +18358,29 @@ class CGBindingRoot(CGThing):
|
||||
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = True
|
||||
bindingHeaders["jsapi.h"] = True
|
||||
|
||||
# For things that have [UseCounter] or [InstrumentedProps]
|
||||
descriptorsHaveUseCounters = any(
|
||||
m.getExtendedAttribute("UseCounter")
|
||||
for d in descriptors
|
||||
for m in d.interface.members
|
||||
)
|
||||
descriptorsHaveInstrumentedProps = any(
|
||||
d.instrumentedProps for d in descriptors if d.concrete
|
||||
)
|
||||
descriptorsHaveNeedsMissingPropUseCounters = any(
|
||||
d.needsMissingPropUseCounters for d in descriptors if d.concrete
|
||||
)
|
||||
# For things that have [UseCounter] or [InstrumentedProps] or [Trial]
|
||||
for d in descriptors:
|
||||
if d.concrete:
|
||||
if d.instrumentedProps:
|
||||
bindingHeaders["mozilla/UseCounter.h"] = True
|
||||
if d.needsMissingPropUseCounters:
|
||||
bindingHeaders[prefHeader(MISSING_PROP_PREF)] = True
|
||||
if d.interface.isSerializable():
|
||||
bindingHeaders["mozilla/dom/StructuredCloneTags.h"] = True
|
||||
if d.wantsXrays:
|
||||
bindingHeaders["mozilla/Atomics.h"] = True
|
||||
bindingHeaders["mozilla/dom/XrayExpandoClass.h"] = True
|
||||
if d.wantsXrayExpandoClass:
|
||||
bindingHeaders["XrayWrapper.h"] = True
|
||||
for m in d.interface.members:
|
||||
if m.getExtendedAttribute("UseCounter"):
|
||||
bindingHeaders["mozilla/UseCounter.h"] = True
|
||||
if m.getExtendedAttribute("Trial"):
|
||||
bindingHeaders["mozilla/OriginTrials.h"] = True
|
||||
|
||||
bindingHeaders["mozilla/UseCounter.h"] = (
|
||||
descriptorsHaveUseCounters or descriptorsHaveInstrumentedProps
|
||||
)
|
||||
# Make sure to not overwrite existing pref header bits!
|
||||
bindingHeaders[prefHeader(MISSING_PROP_PREF)] = (
|
||||
bindingHeaders.get(prefHeader(MISSING_PROP_PREF))
|
||||
or descriptorsHaveNeedsMissingPropUseCounters
|
||||
)
|
||||
bindingHeaders["mozilla/dom/SimpleGlobalObject.h"] = any(
|
||||
CGDictionary.dictionarySafeToJSONify(d) for d in dictionaries
|
||||
)
|
||||
bindingHeaders["XrayWrapper.h"] = any(
|
||||
d.wantsXrays and d.wantsXrayExpandoClass for d in descriptors
|
||||
)
|
||||
bindingHeaders["mozilla/dom/XrayExpandoClass.h"] = any(
|
||||
d.wantsXrays for d in descriptors
|
||||
)
|
||||
bindingHeaders["mozilla/dom/StructuredCloneTags.h"] = any(
|
||||
d.interface.isSerializable() for d in descriptors
|
||||
)
|
||||
bindingHeaders["mozilla/Atomics.h"] = any(d.wantsXrays for d in descriptors)
|
||||
|
||||
for ancestor in (findAncestorWithInstrumentedProps(d) for d in descriptors):
|
||||
if not ancestor:
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "js/Wrapper.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/OriginTrials.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
#include "mozilla/dom/PrototypeList.h" // auto-generated
|
||||
@ -129,6 +130,15 @@ struct PrefableDisablers {
|
||||
if (secureContext && !IsSecureContextOrObjectIsFromSecureContext(cx, obj)) {
|
||||
return false;
|
||||
}
|
||||
if (trial != OriginTrial(0) &&
|
||||
!OriginTrials::IsEnabled(cx, JS::GetNonCCWObjectGlobal(obj), trial)) {
|
||||
// TODO(emilio): Perhaps reconsider the interaction between [Trial=""] and
|
||||
// [Pref=""].
|
||||
//
|
||||
// In particular, it might be desirable to only check the trial if there
|
||||
// is no pref or the pref is disabled.
|
||||
return false;
|
||||
}
|
||||
if (enabledFunc && !enabledFunc(cx, JS::GetNonCCWObjectGlobal(obj))) {
|
||||
return false;
|
||||
}
|
||||
@ -141,6 +151,9 @@ struct PrefableDisablers {
|
||||
// A boolean indicating whether a Secure Context is required.
|
||||
const bool secureContext;
|
||||
|
||||
// An origin trial controlling the feature.
|
||||
const OriginTrial trial;
|
||||
|
||||
// Bitmask of global names that we should not be exposed in.
|
||||
const uint16_t nonExposedGlobals;
|
||||
|
||||
|
@ -1572,6 +1572,7 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
|
||||
or member.getExtendedAttribute("ChromeOnly")
|
||||
or member.getExtendedAttribute("Pref")
|
||||
or member.getExtendedAttribute("Func")
|
||||
or member.getExtendedAttribute("Trial")
|
||||
or member.getExtendedAttribute("SecureContext")
|
||||
):
|
||||
raise WebIDLError(
|
||||
@ -1783,7 +1784,13 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
|
||||
def hasMembersInSlots(self):
|
||||
return self._ownMembersInSlots != 0
|
||||
|
||||
conditionExtendedAttributes = ["Pref", "ChromeOnly", "Func", "SecureContext"]
|
||||
conditionExtendedAttributes = [
|
||||
"Pref",
|
||||
"ChromeOnly",
|
||||
"Func",
|
||||
"Trial",
|
||||
"SecureContext",
|
||||
]
|
||||
|
||||
def isExposedConditionally(self, exclusions=[]):
|
||||
return any(
|
||||
@ -1960,6 +1967,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||
or identifier == "JSImplementation"
|
||||
or identifier == "HeaderFile"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "Deprecated"
|
||||
):
|
||||
# Known extended attributes that take a string value
|
||||
@ -2046,6 +2054,7 @@ class IDLNamespace(IDLInterfaceOrNamespace):
|
||||
identifier == "Pref"
|
||||
or identifier == "HeaderFile"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
):
|
||||
# Known extended attributes that take a string value
|
||||
if not attr.hasValue():
|
||||
@ -4898,6 +4907,7 @@ class IDLConst(IDLInterfaceMember):
|
||||
identifier == "Pref"
|
||||
or identifier == "ChromeOnly"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "SecureContext"
|
||||
or identifier == "NonEnumerable"
|
||||
):
|
||||
@ -5403,6 +5413,7 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
or identifier == "GetterCanOOM"
|
||||
or identifier == "ChromeOnly"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "SecureContext"
|
||||
or identifier == "Frozen"
|
||||
or identifier == "NewObject"
|
||||
@ -5541,6 +5552,7 @@ class IDLArgument(IDLObjectWithIdentifier):
|
||||
elif self.dictionaryMember and (
|
||||
identifier == "ChromeOnly"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "Pref"
|
||||
):
|
||||
if not self.optional:
|
||||
@ -6390,6 +6402,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
or identifier == "Pref"
|
||||
or identifier == "Deprecated"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "SecureContext"
|
||||
or identifier == "BinaryName"
|
||||
or identifier == "NeedsSubjectPrincipal"
|
||||
@ -6445,6 +6458,7 @@ class IDLConstructor(IDLMethod):
|
||||
or identifier == "SecureContext"
|
||||
or identifier == "Throws"
|
||||
or identifier == "Func"
|
||||
or identifier == "Trial"
|
||||
or identifier == "Pref"
|
||||
or identifier == "UseCounter"
|
||||
):
|
||||
|
@ -990,6 +990,9 @@ class TestInterface : public nsISupports, public nsWrapperCache {
|
||||
void ConditionalOnSecureContext7();
|
||||
void ConditionalOnSecureContext8();
|
||||
|
||||
bool ConditionalOnSecureContext9();
|
||||
void ConditionalOnSecureContext10();
|
||||
|
||||
// Miscellania
|
||||
int32_t AttrWithLenientThis();
|
||||
void SetAttrWithLenientThis(int32_t);
|
||||
|
@ -962,6 +962,10 @@ interface TestInterface {
|
||||
void prefable19();
|
||||
[Pref="dom.webidl.test1", Func="TestFuncControlledMember", ChromeOnly]
|
||||
void prefable20();
|
||||
[Trial="TestTrial"]
|
||||
void prefable21();
|
||||
[Pref="dom.webidl.test1", Trial="TestTrial"]
|
||||
void prefable22();
|
||||
|
||||
// Conditionally exposed methods/attributes involving [SecureContext]
|
||||
[SecureContext]
|
||||
@ -980,6 +984,10 @@ interface TestInterface {
|
||||
void conditionalOnSecureContext7();
|
||||
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
|
||||
void conditionalOnSecureContext8();
|
||||
[SecureContext, Trial="TestTrial"]
|
||||
readonly attribute boolean conditionalOnSecureContext9;
|
||||
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember", Trial="TestTrial"]
|
||||
void conditionalOnSecureContext10();
|
||||
|
||||
// Miscellania
|
||||
[LegacyLenientThis] attribute long attrWithLenientThis;
|
||||
|
@ -758,6 +758,12 @@ interface TestExampleInterface {
|
||||
void prefable18();
|
||||
[Func="TestFuncControlledMember"]
|
||||
void prefable19();
|
||||
[Trial="TestTrial"]
|
||||
void prefable20();
|
||||
[Trial="TestTrial"]
|
||||
readonly attribute boolean prefable21;
|
||||
[Trial="TestTrial", Func="TestFuncControlledMember"]
|
||||
readonly attribute boolean prefable22;
|
||||
|
||||
// Conditionally exposed methods/attributes involving [SecureContext]
|
||||
[SecureContext]
|
||||
@ -776,6 +782,10 @@ interface TestExampleInterface {
|
||||
void conditionalOnSecureContext7();
|
||||
[SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"]
|
||||
void conditionalOnSecureContext8();
|
||||
[SecureContext, Trial="TestTrial"]
|
||||
readonly attribute boolean conditionalOnSecureContext9;
|
||||
[SecureContext, Trial="TestTrial"]
|
||||
void conditionalOnSecureContext10();
|
||||
|
||||
// Miscellania
|
||||
[LegacyLenientThis] attribute long attrWithLenientThis;
|
||||
|
@ -10,6 +10,12 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/Wrapper.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -62,4 +68,22 @@ void OriginTrials::UpdateFromToken(const nsAString& aBase64EncodedToken,
|
||||
mEnabledTrials += trial;
|
||||
}
|
||||
|
||||
bool OriginTrials::IsEnabled(JSContext* aCx, JSObject* aObject,
|
||||
OriginTrial aTrial) {
|
||||
if (nsContentUtils::ThreadsafeIsSystemCaller(aCx)) {
|
||||
return true;
|
||||
}
|
||||
if (NS_IsMainThread()) {
|
||||
if (auto* win = xpc::WindowGlobalOrNull(js::UncheckedUnwrap(aObject))) {
|
||||
if (dom::Document* doc = win->GetExtantDoc()) {
|
||||
return doc->Trials().IsEnabled(aTrial);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// TODO(emilio): Worker support.
|
||||
MOZ_ASSERT_UNREACHABLE("Not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
struct JSContext;
|
||||
class JSObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -34,6 +36,9 @@ class OriginTrials final {
|
||||
return mEnabledTrials.contains(aTrial);
|
||||
}
|
||||
|
||||
// Checks whether a given origin trial is enabled for a given call.
|
||||
static bool IsEnabled(JSContext*, JSObject*, OriginTrial);
|
||||
|
||||
private:
|
||||
EnumSet<OriginTrial> mEnabledTrials;
|
||||
};
|
||||
|
@ -7,7 +7,8 @@ use std::ffi::c_void;
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum OriginTrial {
|
||||
TestTrial,
|
||||
// NOTE(emilio): 0 is reserved for WebIDL usage.
|
||||
TestTrial = 1,
|
||||
}
|
||||
|
||||
impl OriginTrial {
|
||||
|
Loading…
Reference in New Issue
Block a user