Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions inc/liquidappconfigwindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <QTabWidget>
#include <QtGui>
#include <QtWidgets>
#include <QJsonObject>

#include "liquidappicon.hpp"

Expand Down Expand Up @@ -39,6 +40,16 @@ public slots:
static QFrame* separator(void);
static QString getSettingsRequiringRestart(QSettings* liquidAppConfig);
void previewBackground(const QColor& color);
static QString getStorageItemId(const QString& origin, const QString& key);
void setUpStorageTableView(QTableView* tableView, QStandardItemModel* model, const int stretchingColumn);
static QStandardItem* newRemoveButtonItem(void);
void addRemoveButtons(QTableView* tableView, QStandardItemModel* model);
void removeStorageItem(QTableView* tableView, const int row);
void fillCookiesModel(QSettings* liquidAppConfig);
void fillLocalStorageModel(QSettings* liquidAppConfig);
void fillSessionStorageModel(void);
void refreshStorage(const QString& liquidAppName);
bool connectToLiquidApp(void);
void sendPreview(const QByteArray& message);

bool isEditingExistingBool = false;
Expand Down Expand Up @@ -87,6 +98,21 @@ public slots:
QCheckBox* allowThirdPartyCookiesCheckBox;
QTableView* cookiesTableView;
QStandardItemModel* cookiesModel;
QCheckBox* rememberLocalStorageCheckBox;
QTableView* localStorageTableView;
QStandardItemModel* localStorageModel;
QTableView* sessionStorageTableView;
QStandardItemModel* sessionStorageModel;
// What's been removed or edited here, kept on top of what the Liquid app stores (until saved, or discarded)
QSet<QString> removedCookieIds; // As identified in the Liquid app's file
QSet<QString> removedLocalStorageIds; // See getStorageItemId()
QMap<QString, QJsonObject> localStorageEdits; // { "origin", "key", "value" } by ID
QSet<QString> removedSessionStorageIds;
// Latest session storage the Liquid app has sent over: { "origin", "items" }
QJsonObject sessionStorage;
// For showing cookies and local storage items as the Liquid app stores them
QFileSystemWatcher* liquidAppFileWatcher = Q_NULLPTR;
QTimer* storageRefreshTimer = Q_NULLPTR;

// Network tab
QRadioButton* proxyModeSystemRadioButton;
Expand Down
6 changes: 6 additions & 0 deletions inc/liquidappcookiejar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ class LiquidAppCookieJar : public QNetworkCookieJar

void restoreCookies(QWebEngineCookieStore* cookieStore);

// Removes cookies that are no longer in the Liquid app's file (e.g. after getting removed in settings)
void removeCookiesMissingFromConfig(QWebEngineCookieStore* cookieStore);

// How cookies are identified in Liquid apps' files
static QString getCookieId(const QNetworkCookie& cookie);

private:
QSettings* liquidAppConfig;
LiquidAppWindow* liquidAppWindow;
Expand Down
75 changes: 75 additions & 0 deletions inc/liquidapplocalstorage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <QJsonObject>
#include <QObject>
#include <QSet>
#include <QSettings>
#include <QString>
#include <QStringList>

class QTimer;
class QUrl;
class QWebEnginePage;

// Remembers what websites keep in their local storage (window.localStorage) across runs of a Liquid app.
//
// Qt provides no access to local storage, and Liquid apps' profiles are off-the-record (nothing gets written to disk),
// so it's done via Liquid's own JS world (which works even if JavaScript is disabled for the page itself):
// whatever the page keeps there gets read every now and then (and before quitting), and stored in the .liquid file,
// and saved items get put back in place before the website's own code runs, the first time it's visited in a run.
// Only the top-level page's storage is remembered (pages embedded in frames can't be reached this way in Qt 5).
class LiquidAppLocalStorage : public QObject
{
Q_OBJECT

public:
LiquidAppLocalStorage(QWebEnginePage* page, QSettings* liquidAppConfig, QObject* parent = Q_NULLPTR);

// Picks up changes made to settings (whether to remember local storage, items edited in settings)
void reloadConfig(void);

bool isEnabled(void) const;

// The script that reads the page's local storage, and what to do with its result
// (for reading it synchronously right before quitting)
static QString getCaptureScript(void);
void onCaptured(const QString& json);

// Session storage of the page that's currently shown (read only while it's being watched, e.g. by settings)
void setWatchingSessionStorage(const bool watching);
QString getSessionStorageOrigin(void) const;
QJsonObject getSessionStorageItems(void) const;
void removeSessionStorageItems(const QString& origin, const QStringList& keys);

// Stored items: { "origin": { "key": "value", ... }, ... }
static QJsonObject load(QSettings* liquidAppConfig);
static void save(QSettings* liquidAppConfig, const QJsonObject& items);

signals:
void sessionStorageChanged(void);

private:
void capture(void);
void updateCaptureTimer(void);
void updateRestoreScript(void);
void markOriginAsLive(const QString& origin);
void onOriginVisited(const QString& origin);
static QString getOrigin(const QUrl& url);
static QString getRestoreScript(const QJsonObject& savedItems, const QJsonObject& editedItems);

QWebEnginePage* page;
QSettings* liquidAppConfig;
QTimer* captureTimer;
bool isEnabledBool = false;
bool isWatchingSessionStorageBool = false;
QString sessionStorageOrigin;
QJsonObject sessionStorageItems;

// What's known to be in the local storage of each origin
QJsonObject items;
// Origins visited during this run: their local storage in the page is the up-to-date one,
// so it never gets restored from the saved items again (e.g. after the website has removed some of them)
QSet<QString> liveOrigins;
// Origins whose items have been edited in settings, to be put in place once they get visited
QSet<QString> editedOrigins;
};
14 changes: 14 additions & 0 deletions inc/liquidappwindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@

#include "liquidappwebpage.hpp"

class LiquidAppCookieJar;
class QLocalSocket;
class LiquidAppIcon;
class LiquidAppIconFetcher;
class LiquidAppLocalStorage;
class LiquidAppWebPage;
class SnapshotFlashOverlay;
class QPainter;
Expand All @@ -43,6 +46,9 @@ public slots:
void setBackground(const QColor& color);
void setAdditionalCss(const QString& css);
void setFrameless(const bool frameless);
// Keeps sending session storage of the page that's currently shown over the connection, until it closes
void watchSessionStorage(QLocalSocket* connection);
void removeSessionStorageItems(const QString& origin, const QStringList& keys);
void setScrollBarsHidden(const bool hidden);
void onIconChanged(QIcon icon);
void stopLoadingOrExitFullScreenMode(void);
Expand Down Expand Up @@ -92,6 +98,14 @@ public slots:
QIcon pageIcon;
// Fetching the website's icon happens once per run, and only if the Liquid app doesn't have one yet
LiquidAppIconFetcher* iconFetcher = Q_NULLPTR;

// Remembers what websites keep in local storage (if allowed to)
LiquidAppLocalStorage* liquidAppLocalStorage = Q_NULLPTR;
QList<QPointer<QLocalSocket>> sessionStorageWatchers;
void sendSessionStorage(QLocalSocket* connection);

// Keeps cookies in the Liquid app's file
LiquidAppCookieJar* liquidAppCookieJar = Q_NULLPTR;
bool iconFetchAttempted = false;

// Settings dialog, while it's open
Expand Down
11 changes: 11 additions & 0 deletions inc/lqd.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#define LQD_INSTANCE_MSG_PREVIEW_FRAME "preview-frame" // Liquid apps only, followed by a space and "on" or "off"
#define LQD_INSTANCE_MSG_PREVIEW_SCROLL "preview-scrollbars" // Liquid apps only, followed by a space and "on" or "off"
#define LQD_INSTANCE_MSG_ICON_CHANGED "icon-changed" // Main window only, followed by a space and Liquid app's name
#define LQD_INSTANCE_MSG_WATCH_SESSION_STORAGE "watch-session-storage" // Liquid apps only; they keep sending session storage back
#define LQD_INSTANCE_MSG_SESSION_STORAGE "session-storage" // Sent back to watchers, followed by a space and base64-encoded JSON
#define LQD_INSTANCE_MSG_REMOVE_SESSION_STORAGE "remove-session-storage" // Liquid apps only, followed by a space and base64-encoded JSON
#define LQD_INSTANCE_MSG_STARTED "started" // Main window only, followed by a space and Liquid app's name
#define LQD_ACTIVATION_TOKEN_TIMEOUT 500 // Milliseconds to wait for the compositor to issue an activation token
#define LQD_PREVIEW_CONNECT_TIMEOUT 100 // Milliseconds to wait for connecting to a Liquid app for previewing settings
Expand All @@ -49,11 +52,17 @@
#define LQD_ICON_MAX_FILE_SIZE (4 * 1024 * 1024) // Bytes
#define LQD_ICON_MAX_SVG_SIZE (512 * 1024) // Bytes, larger SVG icons get rasterized
#define LQD_ICON_MAX_SIZE 256 // Pixels, larger icons get scaled down before they get stored
#define LQD_LOCAL_STORAGE_CAPTURE_INTERVAL 2000 // Milliseconds between checks of what websites keep in local storage
#define LQD_UI_REMOVE_BUTTON_COLUMN_WIDTH 28 // Pixels
#define LQD_UI_TOOLTIP_MAX_LENGTH 2000 // Characters of long values shown in tooltips
#define LQD_STORAGE_REFRESH_DELAY 300 // Milliseconds to wait for the .liquid file to settle before re-reading it in settings
#define LQD_LOCAL_STORAGE_QUIT_TIMEOUT 1000 // Milliseconds to wait for reading local storage before quitting
#define LQD_INSTANCE_STOP_TIMEOUT 5000 // Milliseconds to wait for a Liquid app to quit

/* Names of scripts Liquid injects into web pages */
#define LQD_SCRIPT_NAME_ADDITIONAL_CSS "liquid-additional-css"
#define LQD_SCRIPT_NAME_ADDITIONAL_JS "liquid-additional-js"
#define LQD_SCRIPT_NAME_LOCAL_STORAGE "liquid-local-storage"

/* Textual icons */
#define LQD_ICON_ADD "➕"
Expand Down Expand Up @@ -87,6 +96,7 @@
#define LQD_CFG_KEY_NAME_ENABLE_JS "EnableJS" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_HIDE_SCROLLBARS "HideScrollBars" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_ICON "Icon" // text
#define LQD_CFG_KEY_NAME_LOCAL_STORAGE "LocalStorage" // text, JSON: { "origin": { "key": "value", ... }, ... }
#define LQD_CFG_KEY_NAME_LOCK_WIN_GEOM "LockWindowGeometry" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_MUTE_AUDIO "MuteAudio" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_NOTES "Notes" // text
Expand All @@ -96,6 +106,7 @@
#define LQD_CFG_KEY_NAME_PROXY_USE_SOCKS LQD_CFG_GROUP_NAME_PROXY "/" "UseSocks" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_PROXY_USER_NAME LQD_CFG_GROUP_NAME_PROXY "/" "UserName" // text
#define LQD_CFG_KEY_NAME_PROXY_USER_PASSWORD LQD_CFG_GROUP_NAME_PROXY "/" "UserPassword" // text
#define LQD_CFG_KEY_NAME_REMEMBER_LOCAL_STORAGE "RememberLocalStorage" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_REMOVE_WINDOW_FRAME "RemoveWindowFrame" // boolean, defaults to FALSE
#define LQD_CFG_KEY_NAME_TITLE "Title" // text
#define LQD_CFG_KEY_NAME_USE_PROXY "UseProxy" // boolean, defaults to FALSE
Expand Down
3 changes: 3 additions & 0 deletions inc/singleinstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <QString>

class QLocalServer;
class QLocalSocket;

// Ensures that only one instance (of the main window, or of each Liquid app) runs at a time,
// and lets other processes talk to the one that's running, using local sockets (named pipes on Windows).
Expand All @@ -30,6 +31,8 @@ class SingleInstance : public QObject

signals:
void messageReceived(const QByteArray& message);
// The same, along with the connection it came through (for replying, or for keeping on sending things over it)
void messageReceivedFrom(QLocalSocket* connection, const QByteArray& message);

private:
QString instanceId;
Expand Down
2 changes: 2 additions & 0 deletions liquid.pro
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ HEADERS += inc/lqd.h \
inc/liquid.hpp \
inc/liquidappfile.hpp \
inc/liquidappicon.hpp \
inc/liquidapplocalstorage.hpp \
inc/liquidappcookiejar.hpp \
inc/liquidappconfigwindow.hpp \
inc/liquidappwebpage.hpp \
Expand All @@ -37,6 +38,7 @@ HEADERS += inc/lqd.h \
SOURCES += src/liquid.cpp \
src/liquidappfile.cpp \
src/liquidappicon.cpp \
src/liquidapplocalstorage.cpp \
src/liquidappcookiejar.cpp \
src/liquidappconfigwindow.cpp \
src/liquidappwebpage.cpp \
Expand Down
Loading
Loading