From 9ef413e46176ec60351fd1da098851dea1982e98 Mon Sep 17 00:00:00 2001 From: Reuben Morais Date: Thu, 24 Jul 2014 16:57:02 -0300 Subject: [PATCH] Bug 1009645 - Remove FeatureDetectible, add things with CheckPermissions or AvailableIn to the feature list instead. r=smaug --- dom/base/Navigator.cpp | 77 ++++++++++++++++++++++++- dom/base/Navigator.h | 3 + dom/base/test/mochitest.ini | 1 + dom/base/test/test_hasFeature.html | 78 ++++++++++++++++++++++++++ dom/bindings/Configuration.py | 30 ++++++---- dom/bindings/parser/WebIDL.py | 49 +--------------- dom/permission/tests/test_idle.html | 1 - dom/webidl/Navigator.webidl | 7 ++- dom/webidl/ResourceStats.webidl | 3 - dom/webidl/ResourceStatsManager.webidl | 2 - 10 files changed, 185 insertions(+), 66 deletions(-) create mode 100644 dom/base/test/test_hasFeature.html diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 03d5b45a283..c39aafc1808 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1542,9 +1542,82 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) } } + p->MaybeResolve(JS::UndefinedHandleValue); + return p.forget(); +} + +already_AddRefed +Navigator::HasFeature(const nsAString& aName, ErrorResult& aRv) +{ + nsCOMPtr go = do_QueryInterface(mWindow); + nsRefPtr p = Promise::Create(go, aRv); + if (aRv.Failed()) { + return nullptr; + } + NS_NAMED_LITERAL_STRING(apiWindowPrefix, "api.window."); if (StringBeginsWith(aName, apiWindowPrefix)) { const nsAString& featureName = Substring(aName, apiWindowPrefix.Length()); + + // Temporary hardcoded entry points due to technical constraints + if (featureName.EqualsLiteral("Navigator.mozTCPSocket")) { + p->MaybeResolve(Preferences::GetBool("dom.mozTCPSocket.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozMobileConnections") || + featureName.EqualsLiteral("MozMobileNetworkInfo")) { + p->MaybeResolve(Preferences::GetBool("dom.mobileconnection.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozInputMethod")) { + p->MaybeResolve(Preferences::GetBool("dom.mozInputMethod.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozContacts")) { + p->MaybeResolve(true); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.getDeviceStorage")) { + p->MaybeResolve(Preferences::GetBool("device.storage.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozNetworkStats")) { + p->MaybeResolve(Preferences::GetBool("dom.mozNetworkStats.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.push")) { + p->MaybeResolve(Preferences::GetBool("services.push.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozAlarms")) { + p->MaybeResolve(Preferences::GetBool("dom.mozAlarms.enabled")); + return p.forget(); + } + + if (featureName.EqualsLiteral("Navigator.mozCameras")) { + p->MaybeResolve(true); + return p.forget(); + } + +#ifdef MOZ_B2G + if (featureName.EqualsLiteral("Navigator.getMobileIdAssertion")) { + p->MaybeResolve(true); + return p.forget(); + } +#endif + + if (featureName.EqualsLiteral("XMLHttpRequest.mozSystem")) { + p->MaybeResolve(true); + return p.forget(); + } + if (IsFeatureDetectible(featureName)) { p->MaybeResolve(true); } else { @@ -1559,7 +1632,6 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) return p.forget(); } - PowerManager* Navigator::GetMozPower(ErrorResult& aRv) { @@ -2371,7 +2443,8 @@ Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal) uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION; permMgr->TestPermissionFromPrincipal(principal, "mobileid", &permission); - return permission != nsIPermissionManager::UNKNOWN_ACTION; + return permission == nsIPermissionManager::PROMPT_ACTION || + permission == nsIPermissionManager::ALLOW_ACTION; } #endif diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index f19779c04fa..c676673e095 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -172,6 +172,9 @@ public: already_AddRefed GetFeature(const nsAString& aName, ErrorResult& aRv); + already_AddRefed HasFeature(const nsAString &aName, + ErrorResult& aRv); + bool Vibrate(uint32_t aDuration); bool Vibrate(const nsTArray& aDuration); uint32_t MaxTouchPoints(); diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index c988349f39f..8b8ac1b030c 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -43,6 +43,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1 [test_gsp-standards.html] [test_getFeature_with_perm.html] [test_getFeature_without_perm.html] +[test_hasFeature.html] [test_history_document_open.html] [test_history_state_null.html] [test_Image_constructor.html] diff --git a/dom/base/test/test_hasFeature.html b/dom/base/test/test_hasFeature.html new file mode 100644 index 00000000000..6ccab8aff0c --- /dev/null +++ b/dom/base/test/test_hasFeature.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 1009645 + + + + +Mozilla Bug 1009645 + + + diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 0fa5b5328f8..2a97393531b 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -447,17 +447,27 @@ class Descriptor(DescriptorProvider): if permissionsIndex is not None: self.checkPermissionsIndicesForMembers[m.identifier.name] = permissionsIndex - self.featureDetectibleThings = set() - if self.interface.getExtendedAttribute("FeatureDetectible") is not None: - if self.interface.getNavigatorProperty(): - self.featureDetectibleThings.add("Navigator.%s" % self.interface.getNavigatorProperty()) - else: - assert(self.interface.ctor() is not None) - self.featureDetectibleThings.add(self.interface.identifier.name) + def isTestInterface(iface): + return (iface.identifier.name in ["TestInterface", + "TestJSImplInterface", + "TestRenamedInterface"]) - for m in self.interface.members: - if m.getExtendedAttribute("FeatureDetectible") is not None: - self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name)) + self.featureDetectibleThings = set() + if not isTestInterface(self.interface): + if (self.interface.getExtendedAttribute("CheckPermissions") or + self.interface.getExtendedAttribute("AvailableIn") == "PrivilegedApps"): + if self.interface.getNavigatorProperty(): + self.featureDetectibleThings.add("Navigator.%s" % self.interface.getNavigatorProperty()) + else: + iface = self.interface.identifier.name + self.featureDetectibleThings.add(iface) + for m in self.interface.members: + self.featureDetectibleThings.add("%s.%s" % (iface, m.identifier.name)) + + for m in self.interface.members: + if (m.getExtendedAttribute("CheckPermissions") or + m.getExtendedAttribute("AvailableIn") == "PrivilegedApps"): + self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name)) # Build the prototype chain. self.prototypeChain = [] diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index acc7fcdf565..930af4e12fa 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -669,22 +669,6 @@ class IDLInterface(IDLObjectWithScope): [self.location]) assert not parent or isinstance(parent, IDLInterface) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - if not self.hasInterfaceObject(): - raise WebIDLError("[FeatureDetectible] not allowed on interface " - "with [NoInterfaceObject]", - [self.location]) - self.parent = parent assert iter(self.members) @@ -1207,8 +1191,7 @@ class IDLInterface(IDLObjectWithScope): identifier == "OverrideBuiltins" or identifier == "ChromeOnly" or identifier == "Unforgeable" or - identifier == "LegacyEventInit" or - identifier == "FeatureDetectible"): + identifier == "LegacyEventInit"): # Known extended attributes that do not take values if not attr.noArguments(): raise WebIDLError("[%s] must take no arguments" % identifier, @@ -3174,18 +3157,6 @@ class IDLAttribute(IDLInterfaceMember): raise WebIDLError("An attribute with [SameObject] must have an " "interface type as its type", [self.location]) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - def validate(self): IDLInterfaceMember.validate(self) @@ -3324,8 +3295,7 @@ class IDLAttribute(IDLInterfaceMember): identifier == "Frozen" or identifier == "AvailableIn" or identifier == "NewObject" or - identifier == "CheckPermissions" or - identifier == "FeatureDetectible"): + identifier == "CheckPermissions"): # Known attributes that we don't need to do anything with here pass else: @@ -3730,18 +3700,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def finish(self, scope): IDLInterfaceMember.finish(self, scope) - if self.getExtendedAttribute("FeatureDetectible"): - if not (self.getExtendedAttribute("Func") or - self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")): - raise WebIDLError("[FeatureDetectible] is only allowed in combination " - "with [Func], [AvailableIn] or [CheckPermissions]", - [self.location]) - if self.getExtendedAttribute("Pref"): - raise WebIDLError("[FeatureDetectible] must not be specified " - "in combination with [Pref]", - [self.location]) - overloadWithPromiseReturnType = None overloadWithoutPromiseReturnType = None for overload in self._overloads: @@ -3922,8 +3880,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) elif (identifier == "Pure" or identifier == "CrossOriginCallable" or - identifier == "WebGLHandlesContextLoss" or - identifier == "FeatureDetectible"): + identifier == "WebGLHandlesContextLoss"): # Known no-argument attributes. if not attr.noArguments(): raise WebIDLError("[%s] must take no arguments" % identifier, diff --git a/dom/permission/tests/test_idle.html b/dom/permission/tests/test_idle.html index 595ee622cf1..ef37c3efd6b 100644 --- a/dom/permission/tests/test_idle.html +++ b/dom/permission/tests/test_idle.html @@ -36,7 +36,6 @@ function verifier(success, failure) { var gData = [ { perm: ["idle"], - settings: [["dom.idle-observers-api.enabled", true]], verifier: verifier.toSource(), } ] diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index b9cccf0cfae..1014855adfb 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -86,6 +86,9 @@ interface NavigatorStorageUtils { interface NavigatorFeatures { [CheckPermissions="feature-detection", Throws] Promise getFeature(DOMString name); + + [CheckPermissions="feature-detection", Throws] + Promise hasFeature(DOMString name); }; // Things that definitely need to be in the spec and and are not for some @@ -195,13 +198,13 @@ partial interface Navigator { /** * Navigator requests to add an idle observer to the existing window. */ - [Throws, CheckPermissions="idle", Pref="dom.idle-observers-api.enabled"] + [Throws, CheckPermissions="idle"] void addIdleObserver(MozIdleObserver aIdleObserver); /** * Navigator requests to remove an idle observer from the existing window. */ - [Throws, CheckPermissions="idle", Pref="dom.idle-observers-api.enabled"] + [Throws, CheckPermissions="idle"] void removeIdleObserver(MozIdleObserver aIdleObserver); /** diff --git a/dom/webidl/ResourceStats.webidl b/dom/webidl/ResourceStats.webidl index 6d6c2f0d210..b356a3eec7e 100644 --- a/dom/webidl/ResourceStats.webidl +++ b/dom/webidl/ResourceStats.webidl @@ -7,7 +7,6 @@ [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/networkStatsData;1"] interface NetworkStatsData { @@ -19,7 +18,6 @@ interface NetworkStatsData [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/powerStatsData;1"] interface PowerStatsData { @@ -30,7 +28,6 @@ interface PowerStatsData [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStats;1"] interface ResourceStats { diff --git a/dom/webidl/ResourceStatsManager.webidl b/dom/webidl/ResourceStatsManager.webidl index d7facef475a..dfb59ea47dc 100644 --- a/dom/webidl/ResourceStatsManager.webidl +++ b/dom/webidl/ResourceStatsManager.webidl @@ -73,7 +73,6 @@ dictionary ResourceStatsAlarmOptions [CheckPermissions="resourcestats-manage", Pref="dom.resource_stats.enabled", AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStatsAlarm;1"] interface ResourceStatsAlarm { @@ -117,7 +116,6 @@ interface ResourceStatsAlarm Pref="dom.resource_stats.enabled", Constructor(ResourceType type), AvailableIn="CertifiedApps", -// FeatureDetectible, // This should be specified after Bug 1009645 is resolved. JSImplementation="@mozilla.org/resourceStatsManager;1"] interface ResourceStatsManager {