diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index a13fafd06b9..413fd6f1043 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4639,7 +4639,8 @@ nsDOMClassInfo::Init() mozilla::dom::oldproxybindings::Register(nameSpaceManager); if (!AzureCanvasEnabled()) { - nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"), NULL); + nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"), + nullptr, nullptr); } sIsInitialized = true; @@ -6790,6 +6791,10 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, return NS_OK; } + if (name_struct->mPrefEnabled && !(*name_struct->mPrefEnabled)()) { + return NS_OK; + } + if (mozilla::dom::DefineConstructor(cx, obj, define, &rv)) { *did_resolve = NS_SUCCEEDED(rv); diff --git a/dom/base/nsScriptNameSpaceManager.cpp b/dom/base/nsScriptNameSpaceManager.cpp index e610d581096..16c30712d78 100644 --- a/dom/base/nsScriptNameSpaceManager.cpp +++ b/dom/base/nsScriptNameSpaceManager.cpp @@ -781,7 +781,8 @@ nsScriptNameSpaceManager::Observe(nsISupports* aSubject, const char* aTopic, void nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName, - mozilla::dom::DefineInterface aDefineDOMInterface) + mozilla::dom::DefineInterface aDefineDOMInterface, + mozilla::dom::PrefEnabled aPrefEnabled) { nsGlobalNameStruct *s = AddToHash(&mGlobalNames, &aName); if (s) { @@ -789,5 +790,6 @@ nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName, s->mType = nsGlobalNameStruct::eTypeNewDOMBinding; } s->mDefineDOMInterface = aDefineDOMInterface; + s->mPrefEnabled = aPrefEnabled; } } diff --git a/dom/base/nsScriptNameSpaceManager.h b/dom/base/nsScriptNameSpaceManager.h index a054cebe866..858a6313b56 100644 --- a/dom/base/nsScriptNameSpaceManager.h +++ b/dom/base/nsScriptNameSpaceManager.h @@ -68,6 +68,7 @@ struct nsGlobalNameStruct // For new style DOM bindings. mozilla::dom::DefineInterface mDefineDOMInterface; + mozilla::dom::PrefEnabled mPrefEnabled; // May be null if not pref controlled private: @@ -139,7 +140,8 @@ public: nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct); void RegisterDefineDOMInterface(const nsAFlatString& aName, - mozilla::dom::DefineInterface aDefineDOMInterface); + mozilla::dom::DefineInterface aDefineDOMInterface, + mozilla::dom::PrefEnabled aPrefEnabled); private: // Adds a new entry to the hash and returns the nsGlobalNameStruct diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 0450671d86c..f69535086ac 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1338,6 +1338,24 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): *aEnabled = true; return !!%s(aCx, global, aReceiver);""" % (getter)) +class CGPrefEnabled(CGAbstractMethod): + """ + A method for testing whether the preference controlling this + interface is enabled. When it's not, the interface should not be + visible on the global. + """ + def __init__(self, descriptor): + CGAbstractMethod.__init__(self, descriptor, 'PrefEnabled', 'bool', []) + + def declare(self): + return CGAbstractMethod.declare(self) + + def define(self): + return CGAbstractMethod.define(self) + + def definition_body(self): + return " return %s::PrefEnabled();" % self.descriptor.nativeType + class CGIsMethod(CGAbstractMethod): def __init__(self, descriptor): args = [Argument('JSObject*', 'obj')] @@ -4999,6 +5017,11 @@ class CGDescriptor(CGThing): if descriptor.interface.hasInterfaceObject(): cgThings.append(CGDefineDOMInterfaceMethod(descriptor)) + if (not descriptor.interface.isExternal() and + # Workers stuff is never pref-controlled + not descriptor.workers and + descriptor.interface.getExtendedAttribute("PrefControlled") is not None): + cgThings.append(CGPrefEnabled(descriptor)) if descriptor.interface.hasInterfacePrototypeObject(): cgThings.append(CGNativePropertyHooks(descriptor)) @@ -5310,12 +5333,16 @@ class CGRegisterProtos(CGAbstractMethod): def _defineMacro(self): return """ -#define REGISTER_PROTO(_dom_class) \\ - aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface);\n\n""" +#define REGISTER_PROTO(_dom_class, _pref_check) \\ + aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);\n\n""" def _undefineMacro(self): return "\n#undef REGISTER_PROTO" def _registerProtos(self): - lines = ["REGISTER_PROTO(%s);" % desc.name + def getPrefCheck(desc): + if desc.interface.getExtendedAttribute("PrefControlled") is None: + return "nullptr" + return "%sBinding::PrefEnabled" % desc.name + lines = ["REGISTER_PROTO(%s, %s);" % (desc.name, getPrefCheck(desc)) for desc in self.config.getDescriptors(hasInterfaceObject=True, isExternal=False, workers=False, diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 6f39f3ec304..4fdd4437769 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -738,6 +738,9 @@ class IDLInterface(IDLObjectWithScope): return loopPoint return None + def getExtendedAttribute(self, name): + return self._extendedAttrDict.get(name, None) + class IDLDictionary(IDLObjectWithScope): def __init__(self, location, parentScope, name, parent, members): assert isinstance(parentScope, IDLScope) diff --git a/js/xpconnect/src/dombindingsgen.py b/js/xpconnect/src/dombindingsgen.py index 019ce7723df..d11ef1244d2 100644 --- a/js/xpconnect/src/dombindingsgen.py +++ b/js/xpconnect/src/dombindingsgen.py @@ -736,7 +736,7 @@ def writeStubFile(filename, config, interfaces): "Register(nsScriptNameSpaceManager* aNameSpaceManager)\n" "{\n" "#define REGISTER_PROTO(_dom_class) \\\n" - " aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Wrapper::DefineDOMInterface);\n\n""" + " aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Wrapper::DefineDOMInterface, nullptr);\n\n""" "\n") for clazz in config.list_classes.itervalues(): f.write(" REGISTER_PROTO(%s);\n" % clazz.name) diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 5f980d768d4..6b82f717e67 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -345,6 +345,9 @@ inline bool IsDOMProxy(JSObject *obj) typedef bool (*DefineInterface)(JSContext *cx, JSObject *global, bool *enabled); +typedef bool +(*PrefEnabled)(); + extern bool DefineStaticJSVals(JSContext *cx); void