aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorAlan Alpert <416365416c@gmail.com>2013-05-17 15:32:19 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 01:09:05 +0200
commitfee79b70773ef26c5d45993c4618d302392b0782 (patch)
tree89c5a0c07eb0c8504ecb1e77ef78b7899d10ed7a /src/qml
parent8850e2eafaba8a6493d3ad5ab584b751eb9a8742 (diff)
Add qmlProtectModule
A C++ analog to the protected qmldir syntax, this is also a potential performance improvement because we can avoid some file system accesses. Change-Id: I41781a6cc72aa65bd2d397800345ea16ef442e90 Reviewed-by: Antti Piira <apiira@blackberry.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc25
-rw-r--r--src/qml/qml/qqml.h3
-rw-r--r--src/qml/qml/qqmlmetatype.cpp58
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp8
5 files changed, 91 insertions, 7 deletions
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 386f9f49df..7d668a4a11 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -413,3 +413,28 @@
Returns non-zero if the registration was sucessful.
*/
+/*!
+ \fn int qmlProtectModule(const QString &uri, int versionMajor);
+ \relates QQmlEngine
+
+ This function protects a module from having types registered into it. This
+ can be used to prevent other plugins from injecting types into your module.
+ It can also be a performance improvement, as it allows the engine to skip
+ checking for the possibility of new types or plugins when this import is
+ reached.
+
+ The performance benefit is primarily seen when registering application
+ specific types from within the application instead of through a plugin.
+ Using qmlProtectModule allows the engine to skip checking for a plugin when
+ that uri is imported, which can be noticeable with slow file systems.
+
+ After this function is called, any attempt to register C++ types into this
+ uri, major version combination will lead to a runtime error. Call this after
+ you have registered all of your types with the engine.
+
+ #include <QtQml> to use this function.
+
+ Returns true if the module was found and locked, otherwise returns false.
+ The module must contain exported types in order to be found.
+*/
+
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index ee69985edb..6082fcda08 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -441,6 +441,9 @@ using namespace QtQml;
#pragma clang diagnostic pop
#endif
+//The C++ version of protected namespaces in qmldir
+Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion);
+
template<typename T>
QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
{
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index f3b4d6b1e5..f9583e7a59 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -112,12 +112,15 @@ class QQmlTypeModulePrivate
{
public:
QQmlTypeModulePrivate()
- : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
+ : minMinorVersion(INT_MAX), maxMinorVersion(0), locked(false) {}
+
+ static QQmlTypeModulePrivate* get(QQmlTypeModule* q) { return q->d; }
QQmlMetaTypeData::VersionedUri uri;
int minMinorVersion;
int maxMinorVersion;
+ bool locked;
void add(QQmlType *);
@@ -1126,7 +1129,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
}
// NOTE: caller must hold a QWriteLocker on "data"
-bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName)
+bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName, int majorVersion = -1)
{
if (!typeName.isEmpty()) {
int typeNameLen = typeName.length();
@@ -1158,6 +1161,18 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace));
return false;
}
+ } else if (majorVersion >= 0) {
+ QQmlMetaTypeData::VersionedUri versionedUri;
+ versionedUri.uri = nameSpace;
+ versionedUri.majorVersion = majorVersion;
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
+ if (QQmlTypeModulePrivate::get(qqtm)->locked){
+ QString failure(QCoreApplication::translate("qmlRegisterType",
+ "Cannot install %1 '%2' into protected module '%3' version '%4'"));
+ data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
+ return false;
+ }
+ }
}
}
@@ -1206,7 +1221,7 @@ int registerType(const QQmlPrivate::RegisterType &type)
QWriteLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString elementName = QString::fromUtf8(type.elementName);
- if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName))
+ if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor))
return -1;
int index = data->types.count();
@@ -1226,7 +1241,7 @@ int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
QWriteLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
QString typeName = QString::fromUtf8(type.typeName);
- if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName))
+ if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor))
return -1;
int index = data->types.count();
@@ -1248,7 +1263,7 @@ int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
bool fileImport = false;
if (*(type.uri) == '\0')
fileImport = true;
- if (!checkRegistration(QQmlType::CompositeType, data, fileImport?0:type.uri, typeName))
+ if (!checkRegistration(QQmlType::CompositeType, data, fileImport?0:type.uri, typeName, type.versionMajor))
return -1;
int index = data->types.count();
@@ -1284,6 +1299,23 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
return -1;
}
+//From qqml.h
+bool qmlProtectModule(const char *uri, int majVersion)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlMetaTypeData::VersionedUri versionedUri;
+ versionedUri.uri = QString::fromUtf8(uri);
+ versionedUri.majorVersion = majVersion;
+
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) {
+ QQmlTypeModulePrivate::get(qqtm)->locked = true;
+ return true;
+ }
+ return false;
+}
+
bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri)
{
QQmlMetaTypeData *data = metaTypeData();
@@ -1342,6 +1374,22 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
}
/*
+ Returns true if a module \a uri of this version is installed and locked;
+*/
+bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlMetaTypeData::VersionedUri versionedUri;
+ versionedUri.uri = uri;
+ versionedUri.majorVersion = majVersion;
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0))
+ return QQmlTypeModulePrivate::get(qqtm)->locked;
+ return false;
+}
+
+/*
Returns true if any type or API has been registered for the given \a module with at least
versionMajor.versionMinor, or if types have been registered for \a module with at most
versionMajor.versionMinor.
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index e44eade902..f747049f11 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -113,6 +113,7 @@ public:
static StringConverter customStringConverter(int);
static bool isAnyModule(const QString &uri);
+ static bool isLockedModule(const QString &uri, int majorVersion);
static bool isModule(const QString &module, int versionMajor, int versionMinor);
static QQmlTypeModule *typeModule(const QString &uri, int majorVersion);
@@ -227,7 +228,7 @@ private:
CompositeType = 3
};
friend QString registrationTypeString(RegistrationType);
- friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &);
+ friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &, int);
friend int registerType(const QQmlPrivate::RegisterType &);
friend int registerSingletonType(const QQmlPrivate::RegisterSingletonType &);
friend int registerInterface(const QQmlPrivate::RegisterInterface &);
@@ -262,6 +263,7 @@ private:
friend void addTypeToData(QQmlType* type, QQmlMetaTypeData *data);
friend struct QQmlMetaTypeData;
friend Q_QML_EXPORT void qmlClearTypeRegistrations();
+ friend class QQmlTypeModulePrivate;
QQmlTypeModule();
~QQmlTypeModule();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d138a232b5..23739de3fb 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1252,7 +1252,13 @@ bool QQmlTypeLoader::Blob::addImport(const QQmlScript::Import &import, QList<QQm
QString qmldirFilePath;
QString qmldirUrl;
- if (m_imports.locateQmldir(importDatabase, import.uri, import.majorVersion, import.minorVersion,
+ if (QQmlMetaType::isLockedModule(import.uri, import.majorVersion)) {
+ //Locked modules are checked first, to save on filesystem checks
+ if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
+ import.minorVersion, QString(), QString(), false, errors))
+ return false;
+
+ } else if (m_imports.locateQmldir(importDatabase, import.uri, import.majorVersion, import.minorVersion,
&qmldirFilePath, &qmldirUrl)) {
// This is a local library import
if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,