30#include <QSqlDatabase>
33#include <QStandardPaths>
34#include <QWebEnginePage>
46 migrateFromQupZilla();
49 if (QFileInfo::exists(dir.filePath(QStringLiteral(
"profiles/profiles.ini")))) {
53 std::cout <<
"Falkon: Creating new profile directory" << std::endl;
56 dir.mkpath(dir.absolutePath());
59 dir.mkdir(QStringLiteral(
"profiles"));
60 dir.cd(QStringLiteral(
"profiles"));
63 QFile(dir.filePath(QStringLiteral(
"profiles.ini"))).remove();
64 QFile(QStringLiteral(
":data/profiles.ini")).copy(dir.filePath(QStringLiteral(
"profiles.ini")));
65 QFile(dir.filePath(QStringLiteral(
"profiles.ini"))).setPermissions(QFile::ReadUser | QFile::WriteUser);
67 dir.mkdir(QStringLiteral(
"default"));
68 dir.cd(QStringLiteral(
"default"));
71 QFile(QStringLiteral(
":data/bookmarks.json")).copy(dir.filePath(QStringLiteral(
"bookmarks.json")));
72 QFile(dir.filePath(QStringLiteral(
"bookmarks.json"))).setPermissions(QFile::ReadUser | QFile::WriteUser);
74 QFile versionFile(dir.filePath(QStringLiteral(
"version")));
75 versionFile.open(QFile::WriteOnly);
84 if (profileName.isEmpty()) {
88 profilePath.append(profileName);
93 updateCurrentProfile();
102 if (QDir(dir.absolutePath() + QLatin1Char(
'/') + profileName).exists()) {
105 if (!dir.mkdir(profileName)) {
111 QFile versionFile(dir.filePath(QStringLiteral(
"version")));
112 versionFile.open(QFile::WriteOnly);
135 return path.mid(path.lastIndexOf(QLatin1Char(
'/')) + 1);
142 return settings.value(QStringLiteral(
"Profiles/startProfile"), QLatin1String(
"default")).toString();
149 settings.setValue(QStringLiteral(
"Profiles/startProfile"), profileName);
156 return dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
159void ProfileManager::updateCurrentProfile()
163 if (!profileDir.exists()) {
164 QDir newDir(profileDir.path().remove(profileDir.dirName()));
165 newDir.mkdir(profileDir.dirName());
168 QFile versionFile(profileDir.filePath(QStringLiteral(
"version")));
171 if (versionFile.exists()) {
172 versionFile.open(QFile::ReadOnly);
173 profileVersion = QString::fromUtf8(versionFile.readAll()).trimmed();
176 updateProfile(QString::fromLatin1(
Qz::VERSION), profileVersion);
182 versionFile.open(QFile::WriteOnly);
187void ProfileManager::updateProfile(
const QString ¤t,
const QString &profile)
189 if (current == profile) {
198 if (prof.revisionNumber != 99) {
205 std::cout <<
"Falkon: Using profile from QupZilla " << qPrintable(profile) <<
" is not supported!" << std::endl;
225void ProfileManager::copyDataToProfile()
229 QFile browseData(profileDir.filePath(QStringLiteral(
"browsedata.db")));
231 if (browseData.exists()) {
233 browseData.copy(browseDataBackup);
236 QFile settings(profileDir.filePath(
QSL(
"settings.ini")));
237 if (settings.exists()) {
239 settings.copy(settingsBackup);
243 QFile sessionFile(profileDir.filePath(
QSL(
"session.dat")));
244 if (sessionFile.exists()) {
246 if (oldVersion.isEmpty()) {
247 oldVersion =
QSL(
"unknown-version");
250 sessionFile.copy(sessionBackup);
251 sessionFile.remove();
254 const QString text =
QSL(
"Incompatible profile version has been detected. To avoid losing your profile data, they were "
255 "backed up in following file:<br/><br/><b>") + browseDataBackup +
QSL(
"<br/></b>");
256 QMessageBox::warning(
nullptr, QStringLiteral(
"Falkon: Incompatible profile version"), text);
260void ProfileManager::migrateFromQupZilla()
262 if (
mApp->isPortable()) {
267 const QString qzConfig = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
QL1S(
"/qupzilla");
268#elif defined(Q_OS_MACOS)
269 const QString qzConfig = QDir::homePath() + QLatin1String(
"/Library/Application Support/QupZilla");
271 const QString qzConfig = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) +
QL1S(
"/qupzilla");
274 if (!QFileInfo::exists(qzConfig)) {
278 std::cout <<
"Falkon: Migrating config from QupZilla..." << std::endl;
283void ProfileManager::connectDatabase()
285 QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral(
"QSQLITE"));
287 qCritical() <<
"Qt sqlite database driver is missing! Continuing without database....";
291 if (
mApp->isPrivate()) {
292 db.setConnectOptions(QStringLiteral(
"QSQLITE_OPEN_READONLY"));
298 qCritical() <<
"Cannot open SQLite database! Continuing without database....";
302 if (db.tables().isEmpty()) {
304 for (
const QString &statement : statements) {
305 const QString stmt = statement.trimmed();
306 if (stmt.isEmpty()) {
310 if (!query.exec(stmt)) {
311 qCritical() <<
"Error creating database schema" << query.lastError().text();
319void ProfileManager::updateDatabase()
321 if (QString::fromLatin1(
Qz::VERSION) == profileVersion) {
335 std::cout <<
"Falkon: Using profile from QupZilla " << qPrintable(profileVersion) <<
" is not supported!" << std::endl;
341 std::cout <<
"Falkon: Updating database to version " << qPrintable(QString::fromLatin1(
Qz::VERSION)) << std::endl;
346 query.prepare(QStringLiteral(
347 "CREATE TABLE IF NOT EXISTS site_settings ("
348 "id INTEGER PRIMARY KEY,"
349 "server TEXT NOT NULL,"
351 "zoom_level INTEGER DEFAULT -1,"
352 "allow_cookies INTEGER DEFAULT 0,"
354 "wa_autoload_images INTEGER DEFAULT 0,"
355 "wa_js_enabled INTEGER DEFAULT 0,"
356 "wa_js_open_windows INTEGER DEFAULT 0,"
357 "wa_js_access_clipboard INTEGER DEFAULT 0,"
358 "wa_js_can_paste INTEGER DEFAULT 0,"
359 "wa_js_window_activation INTEGER DEFAULT 0,"
360 "wa_local_storage INTEGER DEFAULT 0,"
361 "wa_fullscreen_support INTEGER DEFAULT 0,"
362 "wa_run_insecure_content INTEGER DEFAULT 0,"
363 "wa_playback_needs_gesture INTEGER DEFAULT 0,"
364 "wa_reading_from_canvas INTEGER DEFAULT 0,"
365 "wa_force_dark_mode INTEGER DEFAULT 0,"
367 "f_notifications INTEGER DEFAULT 0,"
368 "f_geolocation INTEGER DEFAULT 0,"
369 "f_media_audio_capture INTEGER DEFAULT 0,"
370 "f_media_video_capture INTEGER DEFAULT 0,"
371 "f_media_audio_video_capture INTEGER DEFAULT 0,"
372 "f_mouse_lock INTEGER DEFAULT 0,"
373 "f_desktop_video_capture INTEGER DEFAULT 0,"
374 "f_desktop_audio_video_capture INTEGER DEFAULT 0"
379 qCritical() <<
"Error while creating table 'site_settings' in database: " << query.lastError().text();
380 qFatal(
"ProfileManager::updateDatabase Unable to create table 'site_settings' in the database!");
383 query.prepare(QStringLiteral(
384 "CREATE UNIQUE INDEX IF NOT EXISTS site_settings_server_uniqueindex ON site_settings (server);"
388 qFatal() <<
"Error while creating unique index for table 'site_settings': " << query.lastError().text();
391 const QHash<QWebEnginePage::Feature, QString> html5SettingPairs = {
392 {QWebEnginePage::Notifications,
QSL(
"Notifications")},
393 {QWebEnginePage::Geolocation,
QSL(
"Geolocation")},
394 {QWebEnginePage::MediaAudioCapture,
QSL(
"MediaAudioCapture")},
395 {QWebEnginePage::MediaVideoCapture,
QSL(
"MediaVideoCapture")},
396 {QWebEnginePage::MediaAudioVideoCapture,
QSL(
"MediaAudioVideoCapture")},
397 {QWebEnginePage::MouseLock,
QSL(
"MouseLock")},
398 {QWebEnginePage::DesktopVideoCapture,
QSL(
"DesktopVideoCapture")},
399 {QWebEnginePage::DesktopAudioVideoCapture,
QSL(
"DesktopAudioVideoCapture")}
401 QHash<QString, SiteSettingsManager::SiteSettings> siteSettings;
413 for (
auto [feature, settingName] : html5SettingPairs.asKeyValueRange()) {
414 auto const serverList = settings.
value(settingName + suflix, QStringList()).toStringList();
416 for (
const auto &server : serverList) {
417 if (!siteSettings.contains(server)) {
419 for (
auto [f, nameUnused] : html5SettingPairs.asKeyValueRange()) {
424 siteSettings[server].server = server;
425 siteSettings[server].features[feature] = permission;
439 auto const serverList = settings.
value(listName, QStringList()).toStringList();
441 for (
const auto &server : serverList) {
442 if (!siteSettings.contains(server)) {
446 siteSettings[server].server = server;
447 siteSettings[server].AllowCookies = permission;
458 "INSERT INTO site_settings ("
463 "f_media_audio_capture,"
464 "f_media_video_capture,"
465 "f_media_audio_video_capture,"
467 "f_desktop_video_capture,"
468 "f_desktop_audio_video_capture"
470 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
473 for (
const auto &siteSetting : std::as_const(siteSettings)) {
474 query.bindValue(0, siteSetting.server);
475 query.bindValue(1, siteSetting.AllowCookies);
476 query.bindValue(2, siteSetting.features[QWebEnginePage::Notifications]);
477 query.bindValue(3, siteSetting.features[QWebEnginePage::Geolocation]);
478 query.bindValue(4, siteSetting.features[QWebEnginePage::MediaAudioCapture]);
479 query.bindValue(5, siteSetting.features[QWebEnginePage::MediaVideoCapture]);
480 query.bindValue(6, siteSetting.features[QWebEnginePage::MediaAudioVideoCapture]);
481 query.bindValue(7, siteSetting.features[QWebEnginePage::MouseLock]);
482 query.bindValue(8, siteSetting.features[QWebEnginePage::DesktopVideoCapture]);
483 query.bindValue(9, siteSetting.features[QWebEnginePage::DesktopAudioVideoCapture]);
491 qFatal() <<
"Unable to update database.";
static void setCurrentProfilePath(const QString &profilePath)
static QString path(Path type)
static QString currentProfilePath()
void initCurrentProfile(const QString &profileName)
static QString startingProfile()
static QString currentProfile()
static int createProfile(const QString &profileName)
static QStringList availableProfiles()
static bool removeProfile(const QString &profileName)
static void setStartingProfile(const QString &profileName)
void beginGroup(const QString &prefix)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
static void createSettings(const QString &fileName)
static SqlDatabase * instance()
void setDatabase(const QSqlDatabase &database)
FALKON_EXPORT const char * VERSION
SiteSettingsManager::SiteSettings SiteSettings