mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1245650 - remove JavaScript-navigator-property category support. r=bz.
Generate normal properties with getters for things marked as NavigatorProperty, instead of defining these from a resolve hook.
This commit is contained in:
parent
d0fbe5c8f1
commit
f781f02ccd
@ -20,19 +20,10 @@ if (SpecialPowers.hasPermission("alarms", document)) {
|
||||
} else {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.mozAlarms.enabled", true]]}, function() {
|
||||
SpecialPowers.removePermission("alarms", document);
|
||||
|
||||
// mozAlarms is installed on all platforms except Android for the moment.
|
||||
if (navigator.appVersion.indexOf("Android") != -1) {
|
||||
ok(!('mozAlarms' in navigator),
|
||||
"navigator.mozAlarms should not exist without permission");
|
||||
ok(!('AlarmsManager' in window),
|
||||
"Interface AlarmsManager should not exist");
|
||||
} else {
|
||||
ok(!('mozAlarms' in navigator),
|
||||
"navigator.mozAlarms should not exist without permission");
|
||||
ok(!('AlarmsManager' in window),
|
||||
"Interface AlarmsManager should not exist without permission");
|
||||
}
|
||||
ok(!('mozAlarms' in navigator),
|
||||
"navigator.mozAlarms should not exist without permission");
|
||||
ok(!('AlarmsManager' in window),
|
||||
"Interface AlarmsManager should not exist without permission");
|
||||
SpecialPowers.addPermission("alarms", true, document);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
@ -20,7 +20,6 @@ SpecialPowers.pushPrefEnv({"set": [["dom.mozAlarms.enabled", true]]}, function()
|
||||
|
||||
// mozAlarms is installed on all platforms except Android for the moment.
|
||||
if (navigator.appVersion.indexOf("Android") != -1) {
|
||||
ok('AlarmsManager' in window, "Interface AlarmsManager should exist");
|
||||
try {
|
||||
todo('mozAlarms' in navigator,
|
||||
"mozAlarms is not allowed on Android for now. TODO Bug 863557.");
|
||||
@ -30,6 +29,7 @@ SpecialPowers.pushPrefEnv({"set": [["dom.mozAlarms.enabled", true]]}, function()
|
||||
"Caught exception: " + e);
|
||||
}
|
||||
} else {
|
||||
ok('AlarmsManager' in window, "Interface AlarmsManager should exist");
|
||||
ok('mozAlarms' in navigator, "navigator.mozAlarms should exist");
|
||||
ok(navigator.mozAlarms instanceof AlarmsManager,
|
||||
"navigator.mozAlarms should be an instance of AlarmsManager");
|
||||
|
@ -183,7 +183,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
|
||||
tmp->Invalidate();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedResolveResults)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
@ -220,7 +219,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedResolveResults)
|
||||
#ifdef MOZ_EME
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
|
||||
#endif
|
||||
@ -1668,11 +1666,6 @@ Navigator::HasFeature(const nsAString& aName, ErrorResult& aRv)
|
||||
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();
|
||||
@ -2256,206 +2249,6 @@ Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::PropertyDescriptor> aDesc)
|
||||
{
|
||||
// Note: Keep this in sync with MayResolve.
|
||||
if (!JSID_IS_STRING(aId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
|
||||
if (!nameSpaceManager) {
|
||||
return Throw(aCx, NS_ERROR_NOT_INITIALIZED);
|
||||
}
|
||||
|
||||
nsAutoJSString name;
|
||||
if (!name.init(aCx, JSID_TO_STRING(aId))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsGlobalNameStruct* name_struct =
|
||||
nameSpaceManager->LookupNavigatorName(name);
|
||||
if (!name_struct) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> naviObj(aCx,
|
||||
js::CheckedUnwrap(aObject,
|
||||
/* stopAtWindowProxy = */ false));
|
||||
if (!naviObj) {
|
||||
return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
|
||||
ConstructNavigatorProperty construct = name_struct->mConstructNavigatorProperty;
|
||||
MOZ_ASSERT(construct);
|
||||
|
||||
JS::Rooted<JSObject*> domObject(aCx);
|
||||
{
|
||||
// Make sure to do the creation of our object in the compartment
|
||||
// of naviObj, especially since we plan to cache that object.
|
||||
JSAutoCompartment ac(aCx, naviObj);
|
||||
|
||||
// Check whether our constructor is enabled after we unwrap Xrays, since
|
||||
// we don't want to define an interface on the Xray if it's disabled in
|
||||
// the target global, even if it's enabled in the Xray's global.
|
||||
if (name_struct->mConstructorEnabled &&
|
||||
!(*name_struct->mConstructorEnabled)(aCx, naviObj)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name.EqualsLiteral("mozSettings")) {
|
||||
bool hasPermission = CheckPermission("settings-api-read") ||
|
||||
CheckPermission("settings-api-write");
|
||||
if (!hasPermission) {
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.EqualsLiteral("mozDownloadManager")) {
|
||||
if (!CheckPermission("downloads")) {
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nsISupports* existingObject = mCachedResolveResults.GetWeak(name);
|
||||
if (existingObject) {
|
||||
// We know all of our WebIDL objects here are wrappercached, so just go
|
||||
// ahead and WrapObject() them. We can't use GetOrCreateDOMReflector,
|
||||
// because we don't have the concrete type.
|
||||
JS::Rooted<JS::Value> wrapped(aCx);
|
||||
if (!dom::WrapObject(aCx, existingObject, &wrapped)) {
|
||||
return false;
|
||||
}
|
||||
domObject = &wrapped.toObject();
|
||||
} else {
|
||||
domObject = construct(aCx, naviObj);
|
||||
if (!domObject) {
|
||||
return Throw(aCx, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Store the value in our cache
|
||||
nsISupports* native = UnwrapDOMObjectToISupports(domObject);
|
||||
MOZ_ASSERT(native);
|
||||
mCachedResolveResults.Put(name, native);
|
||||
}
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(aCx, &domObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(aDesc, aObject, JS::ObjectValue(*domObject), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
|
||||
"unexpected type");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISupports> native;
|
||||
bool hadCachedNative = mCachedResolveResults.Get(name, getter_AddRefs(native));
|
||||
bool okToUseNative;
|
||||
JS::Rooted<JS::Value> prop_val(aCx);
|
||||
if (hadCachedNative) {
|
||||
okToUseNative = true;
|
||||
} else {
|
||||
native = do_CreateInstance(name_struct->mCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Throw(aCx, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
|
||||
|
||||
if (gpi) {
|
||||
if (!mWindow) {
|
||||
return Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
rv = gpi->Init(mWindow, &prop_val);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Throw(aCx, rv);
|
||||
}
|
||||
}
|
||||
|
||||
okToUseNative = !prop_val.isObjectOrNull();
|
||||
}
|
||||
|
||||
if (okToUseNative) {
|
||||
// Make sure to do the creation of our object in the compartment
|
||||
// of naviObj, especially since we plan to cache that object.
|
||||
JSAutoCompartment ac(aCx, naviObj);
|
||||
|
||||
rv = nsContentUtils::WrapNative(aCx, native, &prop_val);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return Throw(aCx, rv);
|
||||
}
|
||||
|
||||
// Now that we know we managed to wrap this thing properly, go ahead and
|
||||
// cache it as needed.
|
||||
if (!hadCachedNative) {
|
||||
mCachedResolveResults.Put(name, native);
|
||||
}
|
||||
}
|
||||
|
||||
if (!JS_WrapValue(aCx, &prop_val)) {
|
||||
return Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(aDesc, aObject, prop_val, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::MayResolve(jsid aId)
|
||||
{
|
||||
// Note: This function does not fail and may not have any side-effects.
|
||||
// Note: Keep this in sync with DoResolve.
|
||||
if (!JSID_IS_STRING(aId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
|
||||
if (!nameSpaceManager) {
|
||||
// Really shouldn't happen here. Fail safe.
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoString name;
|
||||
AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
|
||||
|
||||
return nameSpaceManager->LookupNavigatorName(name);
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
if (!nameSpaceManager) {
|
||||
NS_ERROR("Can't get namespace manager.");
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
|
||||
for (auto i = nameSpaceManager->NavigatorNameIter(); !i.Done(); i.Next()) {
|
||||
const GlobalNameMapEntry* entry = i.Get();
|
||||
if (!entry->mGlobalName.mConstructorEnabled ||
|
||||
entry->mGlobalName.mConstructorEnabled(aCx, wrapper)) {
|
||||
aNames.AppendElement(entry->mKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Navigator::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
|
@ -309,14 +309,6 @@ public:
|
||||
|
||||
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
|
||||
|
||||
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::PropertyDescriptor> aDesc);
|
||||
// The return value is whether DoResolve might end up resolving the given id.
|
||||
// If in doubt, return true.
|
||||
static bool MayResolve(jsid aId);
|
||||
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
|
||||
ErrorResult& aRv);
|
||||
void GetLanguages(nsTArray<nsString>& aLanguages);
|
||||
|
||||
bool MozE10sEnabled();
|
||||
@ -422,13 +414,6 @@ private:
|
||||
RefPtr<DeviceStorageAreaListener> mDeviceStorageAreaListener;
|
||||
RefPtr<Presentation> mPresentation;
|
||||
|
||||
// Hashtable for saving cached objects DoResolve created, so we don't create
|
||||
// the object twice if asked for it twice, whether due to use of "delete" or
|
||||
// due to Xrays. We could probably use a nsJSThingHashtable here, but then
|
||||
// we'd need to figure out exactly how to trace that, and that seems to be
|
||||
// rocket science. :(
|
||||
nsInterfaceHashtable<nsStringHashKey, nsISupports> mCachedResolveResults;
|
||||
|
||||
nsTArray<RefPtr<Promise> > mVRGetDevicesPromises;
|
||||
};
|
||||
|
||||
|
@ -4239,13 +4239,7 @@ nsGlobalWindow::MayResolve(jsid aId)
|
||||
nsAutoString name;
|
||||
AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
|
||||
|
||||
const nsGlobalNameStruct *name_struct =
|
||||
nameSpaceManager->LookupName(name);
|
||||
|
||||
// LookupName only returns structs for the global.
|
||||
MOZ_ASSERT_IF(name_struct,
|
||||
name_struct->mType != nsGlobalNameStruct::eTypeNavigatorProperty);
|
||||
return name_struct;
|
||||
return nameSpaceManager->LookupName(name);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -17,7 +17,4 @@
|
||||
#define JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY \
|
||||
"JavaScript-global-privileged-property"
|
||||
|
||||
#define JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY \
|
||||
"JavaScript-navigator-property"
|
||||
|
||||
#endif /* nsIScriptNameSpaceManager_h__ */
|
||||
|
@ -100,8 +100,6 @@ static const PLDHashTableOps hash_table_ops =
|
||||
nsScriptNameSpaceManager::nsScriptNameSpaceManager()
|
||||
: mGlobalNames(&hash_table_ops, sizeof(GlobalNameMapEntry),
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH)
|
||||
, mNavigatorNames(&hash_table_ops, sizeof(GlobalNameMapEntry),
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
|
||||
}
|
||||
@ -113,10 +111,10 @@ nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
|
||||
}
|
||||
|
||||
nsGlobalNameStruct *
|
||||
nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const nsAString *aKey,
|
||||
nsScriptNameSpaceManager::AddToHash(const nsAString *aKey,
|
||||
const char16_t **aClassName)
|
||||
{
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(aTable->Add(aKey, fallible));
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(mGlobalNames.Add(aKey, fallible));
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -129,10 +127,9 @@ nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const nsAString *aKey,
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptNameSpaceManager::RemoveFromHash(PLDHashTable *aTable,
|
||||
const nsAString *aKey)
|
||||
nsScriptNameSpaceManager::RemoveFromHash(const nsAString *aKey)
|
||||
{
|
||||
aTable->Remove(aKey);
|
||||
mGlobalNames.Remove(aKey);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -176,9 +173,6 @@ nsScriptNameSpaceManager::Init()
|
||||
rv = FillHash(cm, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initial filling of the has table has been done.
|
||||
// Now, listen for changes.
|
||||
nsCOMPtr<nsIObserverService> serv =
|
||||
@ -192,9 +186,9 @@ nsScriptNameSpaceManager::Init()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsGlobalNameStruct*
|
||||
nsScriptNameSpaceManager::LookupNameInternal(const nsAString& aName,
|
||||
const char16_t **aClassName)
|
||||
const nsGlobalNameStruct*
|
||||
nsScriptNameSpaceManager::LookupName(const nsAString& aName,
|
||||
const char16_t **aClassName)
|
||||
{
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(mGlobalNames.Search(&aName));
|
||||
|
||||
@ -211,14 +205,6 @@ nsScriptNameSpaceManager::LookupNameInternal(const nsAString& aName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const nsGlobalNameStruct*
|
||||
nsScriptNameSpaceManager::LookupNavigatorName(const nsAString& aName)
|
||||
{
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(mNavigatorNames.Search(&aName));
|
||||
|
||||
return entry ? &entry->mGlobalName : nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
|
||||
int32_t aDOMClassInfoID,
|
||||
@ -230,7 +216,7 @@ nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
|
||||
NS_ERROR("Trying to register a non-ASCII class name");
|
||||
return NS_OK;
|
||||
}
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName, aResult);
|
||||
nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
@ -265,7 +251,7 @@ nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
|
||||
|
||||
*aFoundOld = false;
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
|
||||
nsGlobalNameStruct *s = AddToHash(aClassName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
|
||||
@ -298,8 +284,6 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY) == 0 ||
|
||||
strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0) {
|
||||
type = nsGlobalNameStruct::eTypeProperty;
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY) == 0) {
|
||||
type = nsGlobalNameStruct::eTypeNavigatorProperty;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -315,28 +299,19 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory
|
||||
nsresult rv = strWrapper->GetData(categoryEntry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PLDHashTable *table;
|
||||
if (type == nsGlobalNameStruct::eTypeNavigatorProperty) {
|
||||
table = &mNavigatorNames;
|
||||
} else {
|
||||
table = &mGlobalNames;
|
||||
}
|
||||
|
||||
// We need to handle removal before calling GetCategoryEntry
|
||||
// because the category entry is already removed before we are
|
||||
// notified.
|
||||
if (aRemove) {
|
||||
NS_ConvertASCIItoUTF16 entry(categoryEntry);
|
||||
const nsGlobalNameStruct *s =
|
||||
type == nsGlobalNameStruct::eTypeNavigatorProperty ?
|
||||
LookupNavigatorName(entry) : LookupNameInternal(entry);
|
||||
const nsGlobalNameStruct *s = LookupName(entry);
|
||||
// Verify mType so that this API doesn't remove names
|
||||
// registered by others.
|
||||
if (!s || s->mType != type) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RemoveFromHash(table, &entry);
|
||||
RemoveFromHash(&entry);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -345,11 +320,8 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory
|
||||
getter_Copies(contractId));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (type == nsGlobalNameStruct::eTypeNavigatorProperty ||
|
||||
type == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
bool isNavProperty = type == nsGlobalNameStruct::eTypeNavigatorProperty;
|
||||
nsPrintfCString prefName("dom.%s.disable.%s",
|
||||
isNavProperty ? "navigator-property" : "global-constructor",
|
||||
if (type == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
nsPrintfCString prefName("dom.global-constructor.disable.%s",
|
||||
categoryEntry.get());
|
||||
if (Preferences::GetType(prefName.get()) == nsIPrefBranch::PREF_BOOL &&
|
||||
Preferences::GetBool(prefName.get(), false)) {
|
||||
@ -374,7 +346,7 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory
|
||||
nsCID cid = *cidPtr;
|
||||
free(cidPtr);
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
|
||||
nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
|
||||
@ -447,7 +419,7 @@ nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName,
|
||||
mozilla::dom::DefineInterface aDefineDOMInterface,
|
||||
mozilla::dom::ConstructorEnabled* aConstructorEnabled)
|
||||
{
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, &aName);
|
||||
nsGlobalNameStruct *s = AddToHash(&aName);
|
||||
if (s) {
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
|
||||
s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
|
||||
@ -457,22 +429,6 @@ nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptNameSpaceManager::RegisterNavigatorDOMConstructor(
|
||||
const nsAFlatString& aName,
|
||||
mozilla::dom::ConstructNavigatorProperty aNavConstructor,
|
||||
mozilla::dom::ConstructorEnabled* aConstructorEnabled)
|
||||
{
|
||||
nsGlobalNameStruct *s = AddToHash(&mNavigatorNames, &aName);
|
||||
if (s) {
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
|
||||
s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
|
||||
}
|
||||
s->mConstructNavigatorProperty = aNavConstructor;
|
||||
s->mConstructorEnabled = aConstructorEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ScriptNameSpaceManagerMallocSizeOf)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -497,11 +453,5 @@ nsScriptNameSpaceManager::SizeOfIncludingThis(
|
||||
n += entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
n += mNavigatorNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mNavigatorNames.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(iter.Get());
|
||||
n += entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ struct nsGlobalNameStruct
|
||||
eTypeNotInitialized,
|
||||
eTypeNewDOMBinding,
|
||||
eTypeProperty,
|
||||
eTypeNavigatorProperty,
|
||||
eTypeExternalConstructor,
|
||||
eTypeClassConstructor,
|
||||
eTypeClassProto,
|
||||
@ -59,10 +58,8 @@ struct nsGlobalNameStruct
|
||||
};
|
||||
|
||||
// For new style DOM bindings.
|
||||
union {
|
||||
mozilla::dom::DefineInterface mDefineDOMInterface; // for window
|
||||
mozilla::dom::ConstructNavigatorProperty mConstructNavigatorProperty; // for navigator
|
||||
};
|
||||
mozilla::dom::DefineInterface mDefineDOMInterface;
|
||||
|
||||
// May be null if enabled unconditionally
|
||||
mozilla::dom::ConstructorEnabled* mConstructorEnabled;
|
||||
};
|
||||
@ -103,16 +100,7 @@ public:
|
||||
// It also returns a pointer to the string buffer of the classname
|
||||
// in the nsGlobalNameStruct.
|
||||
const nsGlobalNameStruct* LookupName(const nsAString& aName,
|
||||
const char16_t **aClassName = nullptr)
|
||||
{
|
||||
return LookupNameInternal(aName, aClassName);
|
||||
}
|
||||
|
||||
// Returns a nsGlobalNameStruct for the navigator property aName, or
|
||||
// null if one is not found. The returned nsGlobalNameStruct is only
|
||||
// guaranteed to be valid until the next call to any of the methods
|
||||
// in this class.
|
||||
const nsGlobalNameStruct* LookupNavigatorName(const nsAString& aName);
|
||||
const char16_t **aClassName = nullptr);
|
||||
|
||||
nsresult RegisterClassName(const char *aClassName,
|
||||
int32_t aDOMClassInfoID,
|
||||
@ -137,19 +125,6 @@ public:
|
||||
aConstructorEnabled);
|
||||
}
|
||||
|
||||
void RegisterNavigatorDOMConstructor(const nsAFlatString& aName,
|
||||
mozilla::dom::ConstructNavigatorProperty aNavConstructor,
|
||||
mozilla::dom::ConstructorEnabled* aConstructorEnabled);
|
||||
template<size_t N>
|
||||
void RegisterNavigatorDOMConstructor(const char16_t (&aKey)[N],
|
||||
mozilla::dom::ConstructNavigatorProperty aNavConstructor,
|
||||
mozilla::dom::ConstructorEnabled* aConstructorEnabled)
|
||||
{
|
||||
nsLiteralString key(aKey);
|
||||
return RegisterNavigatorDOMConstructor(key, aNavConstructor,
|
||||
aConstructorEnabled);
|
||||
}
|
||||
|
||||
class NameIterator : public PLDHashTable::Iterator
|
||||
{
|
||||
public:
|
||||
@ -170,7 +145,6 @@ public:
|
||||
};
|
||||
|
||||
NameIterator GlobalNameIter() { return NameIterator(&mGlobalNames); }
|
||||
NameIterator NavigatorNameIter() { return NameIterator(&mNavigatorNames); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
@ -181,16 +155,16 @@ private:
|
||||
// that aKey will be mapped to. If mType in the returned
|
||||
// nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
|
||||
// already existed.
|
||||
nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const nsAString *aKey,
|
||||
nsGlobalNameStruct *AddToHash(const nsAString *aKey,
|
||||
const char16_t **aClassName = nullptr);
|
||||
nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,
|
||||
nsGlobalNameStruct *AddToHash(const char *aKey,
|
||||
const char16_t **aClassName = nullptr)
|
||||
{
|
||||
NS_ConvertASCIItoUTF16 key(aKey);
|
||||
return AddToHash(aTable, &key, aClassName);
|
||||
return AddToHash(&key, aClassName);
|
||||
}
|
||||
// Removes an existing entry from the hash.
|
||||
void RemoveFromHash(PLDHashTable *aTable, const nsAString *aKey);
|
||||
void RemoveFromHash(const nsAString *aKey);
|
||||
|
||||
nsresult FillHash(nsICategoryManager *aCategoryManager,
|
||||
const char *aCategory);
|
||||
@ -229,11 +203,7 @@ private:
|
||||
nsISupports* aEntry,
|
||||
bool aRemove);
|
||||
|
||||
nsGlobalNameStruct* LookupNameInternal(const nsAString& aName,
|
||||
const char16_t **aClassName = nullptr);
|
||||
|
||||
PLDHashTable mGlobalNames;
|
||||
PLDHashTable mNavigatorNames;
|
||||
};
|
||||
|
||||
#endif /* nsScriptNameSpaceManager_h__ */
|
||||
|
@ -1663,57 +1663,31 @@ class CGClassConstructor(CGAbstractStaticMethod):
|
||||
|
||||
|
||||
# Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
|
||||
class CGConstructNavigatorObjectHelper(CGAbstractStaticMethod):
|
||||
class CGConstructNavigatorObject(CGAbstractMethod):
|
||||
"""
|
||||
Construct a new JS-implemented WebIDL DOM object, for use on navigator.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
name = "ConstructNavigatorObjectHelper"
|
||||
args = [Argument('JSContext*', 'cx'),
|
||||
Argument('GlobalObject&', 'global'),
|
||||
Argument('JS::Handle<JSObject*>', 'obj'),
|
||||
Argument('ErrorResult&', 'aRv')]
|
||||
rtype = 'already_AddRefed<%s>' % descriptor.name
|
||||
CGAbstractStaticMethod.__init__(self, descriptor, name, rtype, args)
|
||||
|
||||
def definition_body(self):
|
||||
return genConstructorBody(self.descriptor)
|
||||
|
||||
|
||||
class CGConstructNavigatorObject(CGAbstractMethod):
|
||||
"""
|
||||
Wrap a JS-implemented WebIDL object into a JS value, for use on navigator.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
name = 'ConstructNavigatorObject'
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JS::Handle<JSObject*>', 'aObj')]
|
||||
CGAbstractMethod.__init__(self, descriptor, name, 'JSObject*', args)
|
||||
CGAbstractMethod.__init__(self, descriptor, "ConstructNavigatorObject",
|
||||
rtype, args)
|
||||
|
||||
def definition_body(self):
|
||||
if not self.descriptor.interface.isJSImplemented():
|
||||
raise TypeError("Only JS-implemented classes are currently supported "
|
||||
"on navigator. See bug 856820.")
|
||||
return fill(
|
||||
|
||||
return dedent(
|
||||
"""
|
||||
GlobalObject global(aCx, aObj);
|
||||
GlobalObject global(cx, obj);
|
||||
if (global.Failed()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
ErrorResult rv;
|
||||
JS::Rooted<JS::Value> v(aCx);
|
||||
{ // Scope to make sure |result| goes out of scope while |v| is rooted
|
||||
RefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
|
||||
if (rv.MaybeSetPendingException(aCx)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!GetOrCreateDOMReflector(aCx, result, &v)) {
|
||||
//XXX Assertion disabled for now, see bug 991271.
|
||||
MOZ_ASSERT(true || JS_IsExceptionPending(aCx));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return &v.toObject();
|
||||
""",
|
||||
descriptorName=self.descriptor.name)
|
||||
""") + genConstructorBody(self.descriptor)
|
||||
|
||||
|
||||
class CGClassConstructHookHolder(CGGeneric):
|
||||
@ -2501,6 +2475,9 @@ def IsCrossOriginWritable(attr, descriptor):
|
||||
len(crossOriginWritable) == 1)
|
||||
return crossOriginWritable[0] == descriptor.interface.identifier.name
|
||||
|
||||
def isNonExposedNavigatorObjectGetter(attr, descriptor):
|
||||
return (attr.navigatorObjectGetter and
|
||||
not descriptor.getDescriptor(attr.type.inner.identifier.name).register)
|
||||
|
||||
class AttrDefiner(PropertyDefiner):
|
||||
def __init__(self, descriptor, name, static, unforgeable=False):
|
||||
@ -2512,7 +2489,8 @@ class AttrDefiner(PropertyDefiner):
|
||||
attributes = [m for m in descriptor.interface.members if
|
||||
m.isAttr() and m.isStatic() == static and
|
||||
MemberIsUnforgeable(m, descriptor) == unforgeable and
|
||||
isMaybeExposedIn(m, descriptor)]
|
||||
isMaybeExposedIn(m, descriptor) and
|
||||
not isNonExposedNavigatorObjectGetter(m, descriptor)]
|
||||
else:
|
||||
attributes = []
|
||||
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
||||
@ -7123,7 +7101,9 @@ class CGPerSignatureCall(CGThing):
|
||||
IDLType if there's an IDL type involved (including |void|).
|
||||
2) An argument list, which is allowed to be empty.
|
||||
3) A name of a native method to call.
|
||||
4) Whether or not this method is static.
|
||||
4) Whether or not this method is static. Note that this only controls how
|
||||
the method is called (|self->nativeMethodName(...)| vs
|
||||
|nativeMethodName(...)|).
|
||||
|
||||
We also need to know whether this is a method or a getter/setter
|
||||
to do error reporting correctly.
|
||||
@ -7175,7 +7155,7 @@ class CGPerSignatureCall(CGThing):
|
||||
""")))
|
||||
|
||||
deprecated = (idlNode.getExtendedAttribute("Deprecated") or
|
||||
(static and descriptor.interface.getExtendedAttribute("Deprecated")))
|
||||
(idlNode.isStatic() and descriptor.interface.getExtendedAttribute("Deprecated")))
|
||||
if deprecated:
|
||||
cgThings.append(CGGeneric(dedent(
|
||||
"""
|
||||
@ -7191,12 +7171,7 @@ class CGPerSignatureCall(CGThing):
|
||||
"return true;\n")
|
||||
|
||||
argsPre = []
|
||||
if static:
|
||||
nativeType = descriptor.nativeType
|
||||
staticTypeOverride = PropertyDefiner.getStringAttr(idlNode, "StaticClassOverride")
|
||||
if (staticTypeOverride):
|
||||
nativeType = staticTypeOverride
|
||||
nativeMethodName = "%s::%s" % (nativeType, nativeMethodName)
|
||||
if idlNode.isStatic():
|
||||
# If we're a constructor, "obj" may not be a function, so calling
|
||||
# XrayAwareCalleeGlobal() on it is not safe. Of course in the
|
||||
# constructor case either "obj" is an Xray or we're already in the
|
||||
@ -7227,7 +7202,7 @@ class CGPerSignatureCall(CGThing):
|
||||
argsPre.append("cx")
|
||||
|
||||
# Hack for making Promise.prototype.then work well over Xrays.
|
||||
if (not static and
|
||||
if (not idlNode.isStatic() and
|
||||
descriptor.name == "Promise" and
|
||||
idlNode.isMethod() and
|
||||
idlNode.identifier.name == "then"):
|
||||
@ -7290,7 +7265,7 @@ class CGPerSignatureCall(CGThing):
|
||||
needsUnwrappedVar = True
|
||||
argsPre.append("unwrappedObj ? *unwrappedObj : obj")
|
||||
|
||||
if static and not isConstructor and descriptor.name == "Promise":
|
||||
if idlNode.isStatic() and not isConstructor and descriptor.name == "Promise":
|
||||
# Hack for Promise for now: pass in the "this" value to
|
||||
# Promise static methods.
|
||||
argsPre.append("args.thisv()")
|
||||
@ -7394,7 +7369,8 @@ class CGPerSignatureCall(CGThing):
|
||||
cgThings.append(CGCallGenerator(
|
||||
self.isFallible(),
|
||||
self.getArguments(), argsPre, returnType,
|
||||
self.extendedAttributes, descriptor, nativeMethodName,
|
||||
self.extendedAttributes, descriptor,
|
||||
nativeMethodName,
|
||||
static, argsPost=argsPost, resultVar=resultVar))
|
||||
|
||||
if useCounterName:
|
||||
@ -7568,6 +7544,13 @@ class CGMethodCall(CGThing):
|
||||
else:
|
||||
useCounterName = None
|
||||
|
||||
if method.isStatic():
|
||||
nativeType = descriptor.nativeType
|
||||
staticTypeOverride = PropertyDefiner.getStringAttr(method, "StaticClassOverride")
|
||||
if (staticTypeOverride):
|
||||
nativeType = staticTypeOverride
|
||||
nativeMethodName = "%s::%s" % (nativeType, nativeMethodName)
|
||||
|
||||
def requiredArgCount(signature):
|
||||
arguments = signature[1]
|
||||
if len(arguments) == 0:
|
||||
@ -7993,11 +7976,27 @@ class CGGetterCall(CGPerSignatureCall):
|
||||
attr.identifier.name)
|
||||
else:
|
||||
useCounterName = None
|
||||
if attr.isStatic():
|
||||
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
||||
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
|
||||
attr.isStatic(), descriptor, attr,
|
||||
getter=True, useCounterName=useCounterName)
|
||||
|
||||
|
||||
class CGNavigatorGetterCall(CGPerSignatureCall):
|
||||
"""
|
||||
A class to generate a native object getter call for an IDL getter for a
|
||||
property generated by NavigatorProperty.
|
||||
"""
|
||||
def __init__(self, returnType, _, descriptor, attr):
|
||||
nativeMethodName = "%s::ConstructNavigatorObject" % (toBindingNamespace(returnType.inner.identifier.name))
|
||||
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
|
||||
True, descriptor, attr, getter=True)
|
||||
|
||||
def getArguments(self):
|
||||
return [(FakeArgument(BuiltinTypes[IDLBuiltinType.Types.object], self.idlNode), "reflector")]
|
||||
|
||||
|
||||
class FakeIdentifier():
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
@ -8047,6 +8046,8 @@ class CGSetterCall(CGPerSignatureCall):
|
||||
attr.identifier.name)
|
||||
else:
|
||||
useCounterName = None
|
||||
if attr.isStatic():
|
||||
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
||||
CGPerSignatureCall.__init__(self, None,
|
||||
[FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
|
||||
nativeMethodName, attr.isStatic(),
|
||||
@ -8632,8 +8633,12 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
|
||||
else:
|
||||
prefix = ""
|
||||
|
||||
if self.attr.navigatorObjectGetter:
|
||||
cgGetterCall = CGNavigatorGetterCall
|
||||
else:
|
||||
cgGetterCall = CGGetterCall
|
||||
return (prefix +
|
||||
CGGetterCall(self.attr.type, nativeName,
|
||||
cgGetterCall(self.attr.type, nativeName,
|
||||
self.descriptor, self.attr).define())
|
||||
|
||||
@staticmethod
|
||||
@ -11893,6 +11898,8 @@ class CGDescriptor(CGThing):
|
||||
assert descriptor.interface.hasInterfaceObject()
|
||||
cgThings.append(CGStaticGetter(descriptor, m))
|
||||
elif descriptor.interface.hasInterfacePrototypeObject():
|
||||
if isNonExposedNavigatorObjectGetter(m, descriptor):
|
||||
continue
|
||||
cgThings.append(CGSpecializedGetter(descriptor, m))
|
||||
if props.isCrossOriginGetter:
|
||||
crossOriginGetters.add(m.identifier.name)
|
||||
@ -11948,8 +11955,7 @@ class CGDescriptor(CGThing):
|
||||
cgThings.append(CGGenericSetter(descriptor,
|
||||
allowCrossOriginThis=True))
|
||||
|
||||
if descriptor.interface.getNavigatorProperty():
|
||||
cgThings.append(CGConstructNavigatorObjectHelper(descriptor))
|
||||
if descriptor.interface.isNavigatorProperty():
|
||||
cgThings.append(CGConstructNavigatorObject(descriptor))
|
||||
|
||||
if descriptor.concrete and not descriptor.proxy:
|
||||
@ -12020,7 +12026,7 @@ class CGDescriptor(CGThing):
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
|
||||
if ((descriptor.interface.hasInterfaceObject() or descriptor.interface.getNavigatorProperty()) and
|
||||
if ((descriptor.interface.hasInterfaceObject() or descriptor.interface.isNavigatorProperty()) and
|
||||
not descriptor.interface.isExternal() and
|
||||
descriptor.isExposedConditionally()):
|
||||
cgThings.append(CGConstructorEnabled(descriptor))
|
||||
@ -13029,15 +13035,12 @@ class CGRegisterProtos(CGAbstractMethod):
|
||||
aNameSpaceManager->RegisterDefineDOMInterface(MOZ_UTF16(#_dom_class), _dom_class##Binding::DefineDOMInterface, _ctor_check);
|
||||
#define REGISTER_CONSTRUCTOR(_dom_constructor, _dom_class, _ctor_check) \\
|
||||
aNameSpaceManager->RegisterDefineDOMInterface(MOZ_UTF16(#_dom_constructor), _dom_class##Binding::DefineDOMInterface, _ctor_check);
|
||||
#define REGISTER_NAVIGATOR_CONSTRUCTOR(_prop, _dom_class, _ctor_check) \\
|
||||
aNameSpaceManager->RegisterNavigatorDOMConstructor(MOZ_UTF16(_prop), _dom_class##Binding::ConstructNavigatorObject, _ctor_check);
|
||||
""")
|
||||
|
||||
def _undefineMacro(self):
|
||||
return dedent("""
|
||||
#undef REGISTER_CONSTRUCTOR
|
||||
#undef REGISTER_PROTO
|
||||
#undef REGISTER_NAVIGATOR_CONSTRUCTOR
|
||||
""")
|
||||
|
||||
def _registerProtos(self):
|
||||
@ -13054,10 +13057,6 @@ class CGRegisterProtos(CGAbstractMethod):
|
||||
lines.append("REGISTER_PROTO(%s, %s);\n" % (desc.name, getCheck(desc)))
|
||||
lines.extend("REGISTER_CONSTRUCTOR(%s, %s, %s);\n" % (n.identifier.name, desc.name, getCheck(desc))
|
||||
for n in desc.interface.namedConstructors)
|
||||
for desc in self.config.getDescriptors(isNavigatorProperty=True, register=True):
|
||||
propName = desc.interface.getNavigatorProperty()
|
||||
assert propName
|
||||
lines.append('REGISTER_NAVIGATOR_CONSTRUCTOR("%s", %s, %s);\n' % (propName, desc.name, getCheck(desc)))
|
||||
return ''.join(lines)
|
||||
|
||||
def indent_body(self, body):
|
||||
|
@ -225,7 +225,7 @@ class Configuration:
|
||||
elif key == 'isJSImplemented':
|
||||
getter = lambda x: x.interface.isJSImplemented()
|
||||
elif key == 'isNavigatorProperty':
|
||||
getter = lambda x: x.interface.getNavigatorProperty() is not None
|
||||
getter = lambda x: x.interface.isNavigatorProperty()
|
||||
elif key == 'isExposedInAnyWorker':
|
||||
getter = lambda x: x.interface.isExposedInAnyWorker()
|
||||
elif key == 'isExposedInWorkerDebugger':
|
||||
@ -585,6 +585,13 @@ class Descriptor(DescriptorProvider):
|
||||
for attribute in ['implicitJSContext']:
|
||||
addExtendedAttribute(attribute, desc.get(attribute, {}))
|
||||
|
||||
if self.interface.identifier.name == 'Navigator':
|
||||
for m in self.interface.members:
|
||||
if m.isAttr() and m.navigatorObjectGetter:
|
||||
# These getters call ConstructNavigatorObject to construct
|
||||
# the value, and ConstructNavigatorObject needs a JSContext.
|
||||
self.extendedAttributes['all'].setdefault(m.identifier.name, []).append('implicitJSContext')
|
||||
|
||||
self._binaryNames = desc.get('binaryNames', {})
|
||||
self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
|
||||
self._binaryNames.setdefault('__stringifier', 'Stringify')
|
||||
@ -637,13 +644,10 @@ class Descriptor(DescriptorProvider):
|
||||
if (self.interface.getExtendedAttribute("CheckAnyPermissions") or
|
||||
self.interface.getExtendedAttribute("CheckAllPermissions") 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))
|
||||
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("CheckAnyPermissions") or
|
||||
|
@ -578,8 +578,8 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
def isProbablyShortLivingObject(self):
|
||||
return False
|
||||
|
||||
def getNavigatorProperty(self):
|
||||
return None
|
||||
def isNavigatorProperty(self):
|
||||
return False
|
||||
|
||||
def _getDependentObjects(self):
|
||||
return set()
|
||||
@ -1240,7 +1240,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
# interface object, unless they're navigator properties.
|
||||
if (self.isExposedConditionally() and
|
||||
not self.hasInterfaceObject() and
|
||||
not self.getNavigatorProperty()):
|
||||
not self.isNavigatorProperty()):
|
||||
raise WebIDLError("Interface with no interface object is "
|
||||
"exposed conditionally",
|
||||
[self.location])
|
||||
@ -1586,6 +1586,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
current = current.parent
|
||||
return False
|
||||
|
||||
def isNavigatorProperty(self):
|
||||
naviProp = self.getExtendedAttribute("NavigatorProperty")
|
||||
if not naviProp:
|
||||
return False
|
||||
assert len(naviProp) == 1
|
||||
assert isinstance(naviProp, list)
|
||||
assert len(naviProp[0]) != 0
|
||||
return True
|
||||
|
||||
def getNavigatorProperty(self):
|
||||
naviProp = self.getExtendedAttribute("NavigatorProperty")
|
||||
if not naviProp:
|
||||
@ -1593,7 +1602,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
assert len(naviProp) == 1
|
||||
assert isinstance(naviProp, list)
|
||||
assert len(naviProp[0]) != 0
|
||||
return naviProp[0]
|
||||
conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterface.conditionExtendedAttributes
|
||||
attr = IDLAttribute(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
|
||||
IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
|
||||
True,
|
||||
extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
|
||||
navigatorObjectGetter=True)
|
||||
attr._exposureGlobalNames = self._exposureGlobalNames
|
||||
# We're abusing Constant a little bit here, because we need Cached. The
|
||||
# getter will create a new object every time, but we're never going to
|
||||
# clear the cached value.
|
||||
extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
|
||||
IDLExtendedAttribute(self.location, ("Cached", )),
|
||||
IDLExtendedAttribute(self.location, ("Constant", )) ]
|
||||
attr.addExtendedAttributes(extendedAttrs)
|
||||
return attr
|
||||
|
||||
def hasChildInterfaces(self):
|
||||
return self._hasChildInterfaces
|
||||
@ -1611,13 +1635,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
def hasMembersInSlots(self):
|
||||
return self._ownMembersInSlots != 0
|
||||
|
||||
conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
|
||||
"CheckAnyPermissions",
|
||||
"CheckAllPermissions" ]
|
||||
def isExposedConditionally(self):
|
||||
return (self.getExtendedAttribute("Pref") or
|
||||
self.getExtendedAttribute("ChromeOnly") or
|
||||
self.getExtendedAttribute("Func") or
|
||||
self.getExtendedAttribute("AvailableIn") or
|
||||
self.getExtendedAttribute("CheckAnyPermissions") or
|
||||
self.getExtendedAttribute("CheckAllPermissions"))
|
||||
return any(self.getExtendedAttribute(a) for a in self.conditionExtendedAttributes)
|
||||
|
||||
|
||||
class IDLDictionary(IDLObjectWithScope):
|
||||
@ -3372,11 +3394,14 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
AffectsValues = ("Nothing", "Everything")
|
||||
DependsOnValues = ("Nothing", "DOMState", "DeviceState", "Everything")
|
||||
|
||||
def __init__(self, location, identifier, tag):
|
||||
def __init__(self, location, identifier, tag, extendedAttrDict=None):
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
IDLExposureMixins.__init__(self, location)
|
||||
self.tag = tag
|
||||
self._extendedAttrDict = {}
|
||||
if extendedAttrDict is None:
|
||||
self._extendedAttrDict = {}
|
||||
else:
|
||||
self._extendedAttrDict = extendedAttrDict
|
||||
|
||||
def isMethod(self):
|
||||
return self.tag == IDLInterfaceMember.Tags.Method
|
||||
@ -3860,9 +3885,11 @@ class IDLConst(IDLInterfaceMember):
|
||||
|
||||
class IDLAttribute(IDLInterfaceMember):
|
||||
def __init__(self, location, identifier, type, readonly, inherit=False,
|
||||
static=False, stringifier=False, maplikeOrSetlike=None):
|
||||
static=False, stringifier=False, maplikeOrSetlike=None,
|
||||
extendedAttrDict=None, navigatorObjectGetter=False):
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
IDLInterfaceMember.Tags.Attr)
|
||||
IDLInterfaceMember.Tags.Attr,
|
||||
extendedAttrDict=extendedAttrDict)
|
||||
|
||||
assert isinstance(type, IDLType)
|
||||
self.type = type
|
||||
@ -3879,6 +3906,7 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
self.dependsOn = "Everything"
|
||||
self.affects = "Everything"
|
||||
self.navigatorObjectGetter = navigatorObjectGetter
|
||||
|
||||
if static and identifier.name == "prototype":
|
||||
raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
|
||||
@ -6595,11 +6623,26 @@ class Parser(Tokenizer):
|
||||
def finish(self):
|
||||
# If we have interfaces that are iterable, create their
|
||||
# iterator interfaces and add them to the productions array.
|
||||
interfaceStatements = [p for p in self._productions if
|
||||
isinstance(p, IDLInterface)]
|
||||
interfaceStatements = []
|
||||
for p in self._productions:
|
||||
if isinstance(p, IDLInterface):
|
||||
interfaceStatements.append(p)
|
||||
if p.identifier.name == "Navigator":
|
||||
navigatorInterface = p
|
||||
|
||||
iterableIteratorIface = None
|
||||
for iface in interfaceStatements:
|
||||
navigatorProperty = iface.getNavigatorProperty()
|
||||
if navigatorProperty:
|
||||
# We're generating a partial interface to add a readonly
|
||||
# property to the Navigator interface for every interface
|
||||
# annotated with NavigatorProperty.
|
||||
partialInterface = IDLPartialInterface(iface.location,
|
||||
IDLUnresolvedIdentifier(iface.location, "Navigator"),
|
||||
[ navigatorProperty ],
|
||||
navigatorInterface)
|
||||
self._productions.append(partialInterface)
|
||||
|
||||
iterable = None
|
||||
# We haven't run finish() on the interface yet, so we don't know
|
||||
# whether our interface is maplike/setlike/iterable or not. This
|
||||
|
@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=707564
|
||||
var isnot = parent.isnot;
|
||||
|
||||
addLoadEvent(function() {
|
||||
var props = Object.getOwnPropertyNames(frames[0].navigator);
|
||||
var props = Object.getOwnPropertyNames(Object.getPrototypeOf(frames[0].navigator));
|
||||
isnot(props.indexOf("mozContacts"), -1,
|
||||
"Should enumerate a mozContacts property on navigator");
|
||||
|
||||
|
@ -25,7 +25,7 @@ function test()
|
||||
var nav = document.getElementById("t1").contentWindow.navigator;
|
||||
is(nav.foopy, undefined, "We should have an Xray now");
|
||||
is(nav.wrappedJSObject.foopy, 5, "We should have the right navigator object");
|
||||
var props = Object.getOwnPropertyNames(nav);
|
||||
var props = Object.getOwnPropertyNames(Object.getPrototypeOf(nav));
|
||||
isnot(props.indexOf("mozContacts"), -1,
|
||||
"Should enumerate a mozContacts property on navigator xray");
|
||||
|
||||
|
@ -9,34 +9,48 @@
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function makeIframe() {
|
||||
var iframe = document.createElement('iframe');
|
||||
return document.body.appendChild(iframe);
|
||||
}
|
||||
function destroyIframe(iframe) {
|
||||
iframe.remove();
|
||||
}
|
||||
|
||||
function test_no_interface() {
|
||||
ok(!("sync" in navigator), "navigator.sync should not exist without permissions");
|
||||
ok(!("syncManager" in navigator), "navigator.syncManager should not exist without permissions");
|
||||
var iframe = makeIframe();
|
||||
ok(!("sync" in iframe.contentWindow.navigator), "navigator.sync should not exist without permissions");
|
||||
ok(!("syncManager" in iframe.contentWindow.navigator), "navigator.syncManager should not exist without permissions");
|
||||
destroyIframe(iframe);
|
||||
runTests();
|
||||
}
|
||||
|
||||
function test_sync() {
|
||||
ok("register" in navigator.sync, "navigator.sync.register exists");
|
||||
ok("unregister" in navigator.sync, "navigator.sync.unregister exists");
|
||||
ok("registrations" in navigator.sync, "navigator.sync.registrations exists");
|
||||
ok("registration" in navigator.sync, "navigator.sync.registration exists");
|
||||
function test_sync(win) {
|
||||
ok("register" in win.navigator.sync, "navigator.sync.register exists");
|
||||
ok("unregister" in win.navigator.sync, "navigator.sync.unregister exists");
|
||||
ok("registrations" in win.navigator.sync, "navigator.sync.registrations exists");
|
||||
ok("registration" in win.navigator.sync, "navigator.sync.registration exists");
|
||||
}
|
||||
|
||||
function test_sync_interface() {
|
||||
ok("sync" in navigator, "navigator.sync should exist with permissions");
|
||||
ok(!("syncManager" in navigator), "navigator.syncManager should not exist without permissions");
|
||||
var iframe = makeIframe();
|
||||
ok("sync" in iframe.contentWindow.navigator, "navigator.sync should exist with permissions");
|
||||
ok(!("syncManager" in iframe.contentWindow.navigator), "navigator.syncManager should not exist without permissions");
|
||||
|
||||
test_sync();
|
||||
test_sync(iframe.contentWindow);
|
||||
destroyIframe(iframe);
|
||||
runTests();
|
||||
}
|
||||
|
||||
function test_sync_manager_interface() {
|
||||
ok("sync" in navigator, "navigator.sync should exist with permissions");
|
||||
ok("syncManager" in navigator, "navigator.syncManager should exist with permissions");
|
||||
var iframe = makeIframe();
|
||||
ok("sync" in iframe.contentWindow.navigator, "navigator.sync should exist with permissions");
|
||||
ok("syncManager" in iframe.contentWindow.navigator, "navigator.syncManager should exist with permissions");
|
||||
|
||||
test_sync();
|
||||
test_sync(iframe.contentWindow);
|
||||
|
||||
ok("registrations" in navigator.syncManager, "navigator.syncManager.registrations exists");
|
||||
ok("registrations" in iframe.contentWindow.navigator.syncManager, "navigator.syncManager.registrations exists");
|
||||
destroyIframe(iframe);
|
||||
runTests();
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ SpecialPowers.pushPermissions([
|
||||
{type: "settings-api-write", allow: 0, context: document},
|
||||
{type: "settings-clear", allow: 0, context: document}
|
||||
], function() {
|
||||
is(frames[0].navigator.mozSettings, null, "navigator.mozSettings is null when the page doesn't have permissions");
|
||||
is(frames[0].navigator.mozSettings, undefined, "navigator.mozSettings is undefined when the page doesn't have permissions");
|
||||
testPref();
|
||||
});
|
||||
</script>
|
||||
|
@ -22,8 +22,6 @@ SimpleTest.waitForExplicitFinish();
|
||||
var contractId = "@mozilla.org/xmlextras/xmlhttprequest;1";
|
||||
var categoryEntries = [
|
||||
{category: "JavaScript-global-property", entry: "randomname", contractId: contractId},
|
||||
{category: "JavaScript-navigator-property", entry: "randomname1", contractId: contractId},
|
||||
{category: "JavaScript-navigator-property", entry: "randomname2", contractId: contractId},
|
||||
];
|
||||
|
||||
function addCategoryEntries(func) {
|
||||
@ -43,14 +41,10 @@ function removeCategoryEntries(func) {
|
||||
|
||||
function checkNamesPresent() {
|
||||
ok(window.randomname, "window.randomname should return an object");
|
||||
is(typeof(window.navigator.randomname1), 'object', "navigator.randomname1 should return an object");
|
||||
is(typeof(window.navigator.randomname2), 'object', "navigator.randomname1 should return an object");
|
||||
}
|
||||
|
||||
function checkNamesAbsent() {
|
||||
ok(!window.randomname, "window.randomname should return undefined");
|
||||
is(typeof(window.navigator.randomname1), 'undefined', "navigator.randomname1 should return undefined");
|
||||
is(typeof(window.navigator.randomname2), 'undefined', "navigator.randomname1 should return undefined");
|
||||
}
|
||||
|
||||
// Ensure the initial state
|
||||
@ -58,12 +52,8 @@ checkNamesAbsent();
|
||||
|
||||
addCategoryEntries(function test1() {
|
||||
ok(window.randomname, "window.randomname should return an object");
|
||||
is(typeof(window.navigator.randomname1), 'object', "navigator.randomname1 should return an object");
|
||||
is(typeof(window.navigator.randomname2), 'object', "navigator.randomname1 should return an object");
|
||||
|
||||
delete window.randomname;
|
||||
delete window.navigator.randomname1;
|
||||
delete window.navigator.randomname2;
|
||||
|
||||
// The delete opertor should have no effect as long as the category entry is registered.
|
||||
checkNamesPresent();
|
||||
@ -76,8 +66,6 @@ function test2() {
|
||||
checkNamesPresent();
|
||||
|
||||
delete window.randomname;
|
||||
delete window.navigator.randomname1;
|
||||
delete window.navigator.randomname2;
|
||||
|
||||
// Now the delete opertor should have the effect.
|
||||
checkNamesAbsent();
|
||||
|
@ -1026,7 +1026,8 @@ var interfaceNamesInGlobalScope =
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"SettingsLock",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"SettingsManager",
|
||||
{name: "SettingsManager",
|
||||
permission: ["settings-read", "settings-write"]},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"ShadowRoot", // Bogus, but the test harness forces it on. See bug 1159768.
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
@ -17,15 +17,11 @@ enum DownloadState {
|
||||
"finalized"
|
||||
};
|
||||
|
||||
//
|
||||
// XXXTODO: When we have a generic way to do feature detection in marketplace
|
||||
// we will *STOP* using the pref and use CheckAnyPermissions like
|
||||
// DOMDownload and DownloadEvent.
|
||||
//
|
||||
[NoInterfaceObject,
|
||||
NavigatorProperty="mozDownloadManager",
|
||||
JSImplementation="@mozilla.org/downloads/manager;1",
|
||||
Pref="dom.mozDownloads.enabled"]
|
||||
Pref="dom.mozDownloads.enabled",
|
||||
CheckAnyPermissions="downloads"]
|
||||
interface DOMDownloadManager : EventTarget {
|
||||
// This promise returns an array of downloads with all the current
|
||||
// download objects.
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
|
||||
[HeaderFile="Navigator.h", NeedResolve]
|
||||
[HeaderFile="Navigator.h"]
|
||||
interface Navigator {
|
||||
// objects implementing this interface also implement the interfaces given below
|
||||
};
|
||||
|
@ -30,7 +30,8 @@ callback SettingChangeCallback = void (SettingChange setting);
|
||||
|
||||
[JSImplementation="@mozilla.org/settingsManager;1",
|
||||
NavigatorProperty="mozSettings",
|
||||
Pref="dom.mozSettings.enabled"]
|
||||
Pref="dom.mozSettings.enabled",
|
||||
CheckAnyPermissions="settings-api-read settings-api-write"]
|
||||
interface SettingsManager : EventTarget {
|
||||
SettingsLock createLock();
|
||||
|
||||
|
@ -20,7 +20,6 @@ PREPROCESSED_WEBIDL_FILES = [
|
||||
WEBIDL_FILES = [
|
||||
'AbstractWorker.webidl',
|
||||
'ActivityRequestHandler.webidl',
|
||||
'AlarmsManager.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'Animatable.webidl',
|
||||
'Animation.webidl',
|
||||
@ -927,3 +926,8 @@ if CONFIG['MOZ_B2G']:
|
||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||
'MozApplicationEvent.webidl'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
|
||||
WEBIDL_FILES += [
|
||||
'AlarmsManager.webidl',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user