2
* Copyright 2014 Canonical Ltd.
4
* This file is part of webbrowser-app.
6
* webbrowser-app is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 3.
10
* webbrowser-app is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#include "hook-utils.h"
25
#include <QJsonDocument>
26
#include <QJsonObject>
27
#include <QStandardPaths>
33
WebappHookParser::OptionalData
34
WebappHookParser::parseContent(const QString& filename)
36
QFileInfo info(filename);
37
if (!info.exists() || !info.isFile() || !info.isReadable())
39
return OptionalData(Data(), false);
43
if (!file.open(QIODevice::ReadOnly))
45
qWarning() << "Cannot open webapp hook: " << filename;
46
return OptionalData(Data(), false);
49
QJsonDocument document(QJsonDocument::fromJson(file.readAll()));
50
if (document.isNull() || document.isEmpty() || !document.isArray()) {
51
return OptionalData(Data(), false);
54
return parseDocument(document.array());
57
WebappHookParser::OptionalData
58
WebappHookParser::parseDocument(const QJsonArray &array)
61
if (array.count() == 0
62
|| !array.at(0).isObject())
64
return OptionalData(result);
67
QJsonObject rootObject = array.at(0).toObject();
69
#define JSON_OBJECT_VALIDATE(o,key,predicate) \
70
o.contains(key) && o.value(key).predicate()
72
const QString UNINSTALL_KEY = "uninstall";
73
if (JSON_OBJECT_VALIDATE(rootObject,UNINSTALL_KEY,isObject))
75
const QString UNINSTALL_DELETE_COOKIES = "delete-cookies";
76
const QString UNINSTALL_DELETE_CACHE = " ";
78
QJsonObject uninstallObject =
79
rootObject.value(UNINSTALL_KEY).toObject();
80
if (JSON_OBJECT_VALIDATE(uninstallObject,UNINSTALL_DELETE_COOKIES,isBool))
82
result.shouldDeleteCookiesOnUninstall =
83
uninstallObject.value(UNINSTALL_DELETE_COOKIES).toBool();
86
if (JSON_OBJECT_VALIDATE(uninstallObject,UNINSTALL_DELETE_CACHE,isBool))
88
result.shouldDeleteCacheOnUninstall =
89
uninstallObject.value(UNINSTALL_DELETE_CACHE).toBool();
92
#undef JSON_OBJECT_VALIDATE
94
return OptionalData(result);
97
WebappClickHookInstallDescription
98
listWebappClickHookFilesIn(const QDir& dir)
100
WebappClickHookInstallDescription
101
description(dir.absolutePath(), QHash<QString, QString>());
103
const QString WEBAPP_CLICK_HOOK_FILE_EXT = "webapp";
104
Q_FOREACH(const QFileInfo &fileInfo, dir.entryInfoList())
106
if (fileInfo.suffix() == WEBAPP_CLICK_HOOK_FILE_EXT)
108
QString suffix = fileInfo.suffix();
109
description.hookFiles[removeVersionFrom(fileInfo.completeBaseName()) + "." + suffix] =
117
getProcessedClickHooksFolder()
119
QString result = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)
120
+ "/webapp-container";
121
if (!qgetenv("WEBAPPCONTAINER_PROCESSED_HOOKS_FOLDER").isNull())
123
result = QString(qgetenv("WEBAPPCONTAINER_PROCESSED_HOOKS_FOLDER"));
129
getClickHooksInstallFolder()
131
QString result = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
132
+ "/webapp-container";
133
if (!qgetenv("WEBAPPCONTAINER_INSTALLED_HOOKS_FOLDER").isNull())
135
result = QString(qgetenv("WEBAPPCONTAINER_INSTALLED_HOOKS_FOLDER"));
140
QString removeVersionFrom(const QString &appId)
142
QStringList components = appId.split('_');
143
if (components.count() != 3)
147
components.removeLast();
148
return components.join('_');
151
void handleInstalls(const WebappClickHookInstallDescription& alreadyProcessedClickHooks
152
, const WebappClickHookInstallDescription& installedClickHooks)
154
QStringList newlyInstalledClickPackages =
155
installedClickHooks.hookFiles.keys().toSet().subtract(
156
alreadyProcessedClickHooks.hookFiles.keys().toSet()).toList();
158
if (newlyInstalledClickPackages.count() == 0)
160
qDebug() << "Nothing to install.";
164
Q_FOREACH(const QString &webappClickHook, newlyInstalledClickPackages)
166
QString hookFilename =
167
installedClickHooks.parentFolder + "/"
168
+ installedClickHooks.hookFiles[webappClickHook];
170
QFileInfo hookFileInfo(hookFilename);
171
QString suffix = hookFileInfo.suffix();
172
QString appIdNoVersion = removeVersionFrom(hookFileInfo.completeBaseName());
174
QString destination = QString("%1/%2").
175
arg(alreadyProcessedClickHooks.parentFolder).arg(appIdNoVersion + "." + suffix);
177
qDebug() << "Installing: " << destination;
179
QFile::copy(hookFilename, destination);
184
void handleUninstall(const WebappClickHookInstallDescription& alreadyProcessedClickHooks
185
, const WebappClickHookInstallDescription& currentClickHooks)
187
WebappHookParser webappHookParser;
188
QStringList deletedClickPackages =
189
alreadyProcessedClickHooks.hookFiles.keys().toSet().subtract(
190
currentClickHooks.hookFiles.keys().toSet()).toList();
192
if (deletedClickPackages.count() == 0)
194
qDebug() << "Nothing to delete.";
198
Q_FOREACH(const QString &webappClickHook, deletedClickPackages)
200
QString hookFilename =
201
alreadyProcessedClickHooks.parentFolder + "/" + webappClickHook;
203
WebappHookParser::OptionalData optional_data =
204
webappHookParser.parseContent(hookFilename);
205
if (!optional_data.is_valid())
210
QFileInfo fileInfo(hookFilename);
211
QString appIdNoVersion = fileInfo.fileName();
213
WebappHookParser::Data data = optional_data.value();
214
if (data.shouldDeleteCacheOnUninstall)
216
QDir dir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)
217
+ "/" + appIdNoVersion);
218
dir.removeRecursively();
220
if (data.shouldDeleteCookiesOnUninstall)
222
QDir dir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
223
+ "/" + appIdNoVersion);
224
dir.removeRecursively();
227
qDebug() << "Uninstalling: " << hookFilename;
229
QFile::remove(hookFilename);
233
void handleUpdates(const WebappClickHookInstallDescription& alreadyProcessedClickHooks
234
, const WebappClickHookInstallDescription& installedClickHooks)
236
QStringList foundClickHooks =
237
alreadyProcessedClickHooks.hookFiles.keys().toSet().intersect(
238
installedClickHooks.hookFiles.keys().toSet()).toList();
240
if (foundClickHooks.count() == 0)
242
qDebug() << "Nothing to update.";
246
Q_FOREACH(const QString &webappClickHook, foundClickHooks)
248
QString hookFilename =
249
installedClickHooks.parentFolder + "/"
250
+ installedClickHooks.hookFiles[webappClickHook];
252
QFileInfo hookFileInfo(hookFilename);
253
QString suffix = hookFileInfo.suffix();
254
QString appIdNoVersion = removeVersionFrom(hookFileInfo.completeBaseName());
256
QString destination = QString("%1/%2").
257
arg(alreadyProcessedClickHooks.parentFolder).arg(appIdNoVersion + "." + suffix);
259
QFileInfo destinationInfo(destination);
260
if (destinationInfo.exists() &&
261
destinationInfo.lastModified() >= hookFileInfo.lastModified()) {
265
qDebug() << "Updating " << destination;
267
if (QFile::exists(destination))
269
QFile::remove(destination);
272
QFile::copy(hookFilename, destination);