diff options
| author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-20 13:01:08 +0200 |
|---|---|---|
| committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-20 13:01:08 +0200 |
| commit | 49233e234e5c787396cadb2cea33b31ae0cd65c1 (patch) | |
| tree | 5410cb9a8fd53168bb60d62c54b654d86f03c38d /Source/WebKit2/UIProcess/Plugins | |
| parent | b211c645d8ab690f713515dfdc84d80b11c27d2c (diff) | |
| download | qtwebkit-49233e234e5c787396cadb2cea33b31ae0cd65c1.tar.gz | |
Imported WebKit commit 3a8c29f35d00659d2ce7a0ccdfa8304f14e82327 (http://svn.webkit.org/repository/webkit/trunk@120813)
New snapshot with Windows build fixes
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
| -rw-r--r-- | Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp | 195 |
1 files changed, 176 insertions, 19 deletions
diff --git a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp index 9b7f2b2dd..b0a5b230d 100644 --- a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp +++ b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp @@ -29,12 +29,23 @@ #if ENABLE(PLUGIN_PROCESS) #include "ProcessExecutablePath.h" +#include "QtDefaultDataLocation.h" #include <QByteArray> #include <QCoreApplication> +#include <QDateTime> #include <QDir> #include <QEventLoop> +#include <QFile> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QMap> #include <QProcess> -#include <QString> +#include <QStringBuilder> +#include <QVariant> +#include <WebCore/FileSystem.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebKit { @@ -44,35 +55,181 @@ void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationPa { } +static PassOwnPtr<QFile> cacheFile() +{ + static QString cacheFilePath = defaultDataLocation() % QStringLiteral("plugin_meta_data.json"); + return adoptPtr(new QFile(cacheFilePath)); +} + +struct ReadResult { + enum Tag { + Empty, + Error, + Success + }; +}; + +static ReadResult::Tag readMetaDataFromCacheFile(QJsonDocument& result) +{ + OwnPtr<QFile> file = cacheFile(); + if (!file->open(QFile::ReadOnly)) + return ReadResult::Empty; + QByteArray data = file->readAll(); + if (data.isEmpty()) + return ReadResult::Empty; + + QJsonParseError error; + result = QJsonDocument::fromJson(data, &error); + if (error.error != QJsonParseError::NoError || !result.isArray()) { + // Corrupted file. + file->remove(); + return ReadResult::Error; + } + + return ReadResult::Success; +} + +static void writeToCacheFile(const QJsonArray& array) +{ + OwnPtr<QFile> file = cacheFile(); + if (!file->open(QFile::WriteOnly | QFile::Truncate)) { + // It should never but let's be pessimistic, it is the file system after all. + qWarning("Cannot write into plugin meta data cache file: %s\n", qPrintable(file->fileName())); + return; + } + + // Don't care about write error here. We will detect it later. + file->write(QJsonDocument(array).toJson()); +} + +static void appendToCacheFile(const QJsonObject& object) +{ + QJsonDocument jsonDocument; + ReadResult::Tag result = readMetaDataFromCacheFile(jsonDocument); + if (result == ReadResult::Error) + return; + if (result == ReadResult::Empty) + jsonDocument.setArray(QJsonArray()); + + QJsonArray array = jsonDocument.array(); + array.append(object); + writeToCacheFile(array); +} + +struct MetaDataResult { + enum Tag { + NotAvailable, + Unloadable, + Available + }; +}; + +static MetaDataResult::Tag tryReadPluginMetaDataFromCacheFile(const QString& canonicalPluginPath, RawPluginMetaData& result) +{ + QJsonDocument jsonDocument; + if (readMetaDataFromCacheFile(jsonDocument) != ReadResult::Success) + return MetaDataResult::NotAvailable; + + QJsonArray array = jsonDocument.array(); + QDateTime pluginLastModified = QFileInfo(canonicalPluginPath).lastModified(); + for (QJsonArray::const_iterator i = array.constBegin(); i != array.constEnd(); ++i) { + QJsonValue item = *i; + if (!item.isObject()) { + cacheFile()->remove(); + return MetaDataResult::NotAvailable; + } + + QJsonObject object = item.toObject(); + if (object.value(QStringLiteral("path")).toString() == canonicalPluginPath) { + QString timestampString = object.value(QStringLiteral("timestamp")).toString(); + if (timestampString.isEmpty()) { + cacheFile()->remove(); + return MetaDataResult::NotAvailable; + } + QDateTime timestamp = QDateTime::fromString(timestampString); + if (timestamp < pluginLastModified) { + // Out of date data for this plugin => remove it from the file. + array.removeAt(i.i); + writeToCacheFile(array); + return MetaDataResult::NotAvailable; + } + + if (object.contains(QLatin1String("unloadable"))) + return MetaDataResult::Unloadable; + + // Match. + result.name = object.value(QStringLiteral("name")).toString(); + result.description = object.value(QStringLiteral("description")).toString(); + result.mimeDescription = object.value(QStringLiteral("mimeDescription")).toString(); + if (result.mimeDescription.isEmpty()) { + // Only the mime description is mandatory. + // Don't trust in the cache file if it is empty. + cacheFile()->remove(); + return MetaDataResult::NotAvailable; + } + + return MetaDataResult::Available; + } + } + + return MetaDataResult::NotAvailable; +} + bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result) { - QString commandLine = QLatin1String("%1 %2 %3"); - commandLine = commandLine.arg(executablePathOfPluginProcess()); - commandLine = commandLine.arg(QStringLiteral("-scanPlugin")).arg(static_cast<QString>(pluginPath)); + QFileInfo pluginFileInfo(pluginPath); + if (!pluginFileInfo.exists()) + return false; + + MetaDataResult::Tag metaDataResult = tryReadPluginMetaDataFromCacheFile(pluginFileInfo.canonicalFilePath(), result); + if (metaDataResult == MetaDataResult::Available) + return true; + if (metaDataResult == MetaDataResult::Unloadable) + return false; + // Scan the plugin via the plugin process. + QString commandLine = QString(executablePathOfPluginProcess()) % QLatin1Char(' ') + % QStringLiteral("-scanPlugin") % QLatin1Char(' ') % pluginFileInfo.canonicalFilePath(); QProcess process; process.setReadChannel(QProcess::StandardOutput); process.start(commandLine); - if (!process.waitForFinished() - || process.exitStatus() != QProcess::NormalExit - || process.exitCode() != EXIT_SUCCESS) { + bool ranSuccessfully = process.waitForFinished() + && process.exitStatus() == QProcess::NormalExit + && process.exitCode() == EXIT_SUCCESS; + if (ranSuccessfully) { + QByteArray outputBytes = process.readAll(); + ASSERT(!(outputBytes.size() % sizeof(UChar))); + + String output(reinterpret_cast<const UChar*>(outputBytes.constData()), outputBytes.size() / sizeof(UChar)); + Vector<String> lines; + output.split(UChar('\n'), lines); + ASSERT(lines.size() == 3); + + result.name.swap(lines[0]); + result.description.swap(lines[1]); + result.mimeDescription.swap(lines[2]); + } else process.kill(); - return false; - } - QByteArray outputBytes = process.readAll(); - ASSERT(!(outputBytes.size() % sizeof(UChar))); + QVariantMap map; + map[QStringLiteral("path")] = QString(pluginFileInfo.canonicalFilePath()); + map[QStringLiteral("timestamp")] = QDateTime::currentDateTime().toString(); + + if (!ranSuccessfully || result.mimeDescription.isEmpty()) { + // We failed getting the meta data in some way. Cache this information, so we don't + // need to rescan such plugins every time. We will retry it once the plugin is updated. - String output(reinterpret_cast<const UChar*>(outputBytes.constData()), outputBytes.size() / sizeof(UChar)); - Vector<String> lines; - output.split(UChar('\n'), lines); - ASSERT(lines.size() == 3); + map[QStringLiteral("unloadable")] = QStringLiteral("true"); + appendToCacheFile(QJsonObject::fromVariantMap(map)); + return false; + } - result.name.swap(lines[0]); - result.description.swap(lines[1]); - result.mimeDescription.swap(lines[2]); - return !result.mimeDescription.isEmpty(); + map[QStringLiteral("name")] = QString(result.name); + map[QStringLiteral("description")] = QString(result.description); + map[QStringLiteral("mimeDescription")] = QString(result.mimeDescription); + appendToCacheFile(QJsonObject::fromVariantMap(map)); + return true; } } // namespace WebKit |
