diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..1964f99 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +build-* \ No newline at end of file diff --git a/app/README.md b/app/README.md index 15c1c25..a2b2c5c 100644 --- a/app/README.md +++ b/app/README.md @@ -1,10 +1,11 @@ # SysTray-X App -Please be aware that the JSON file needs to be installed in the: +Please be aware that the JSON file needs to be installed in the .mozilla/native-messaging-hosts (Firefox) config directory -and NOT in the .thunderbird/native-messaging-hosts (Thunderbird) config dir. +and NOT in the .thunderbird/native-messaging-hosts (Thunderbird) config dir. + diff --git a/app/README.references.txt b/app/README.references.txt new file mode 100644 index 0000000..6d0d86c --- /dev/null +++ b/app/README.references.txt @@ -0,0 +1,3 @@ +Native messaging + +https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging diff --git a/app/SysTray-X/.gitignore b/app/SysTray-X/.gitignore new file mode 100644 index 0000000..e1158dd --- /dev/null +++ b/app/SysTray-X/.gitignore @@ -0,0 +1,2 @@ +SysTray-X.pro.user +*.autosave diff --git a/app/SysTray-X/SysTray-X.pro b/app/SysTray-X/SysTray-X.pro new file mode 100644 index 0000000..4792009 --- /dev/null +++ b/app/SysTray-X/SysTray-X.pro @@ -0,0 +1,195 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2020-01-12T19:19:44 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = SysTray-X +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +CONFIG += c++11 +#CONFIG += staticlib + +# +# System dependency +# +unix:!macx: { +# QMAKE_LFLAGS += -lX11 -static-libgcc -static-libstdc++ +} +win32: { +# QMAKE_LFLAGS += -static -lwinpthread -static-libgcc -static-libstdc++ $$(QMAKE_LFLAGS_WINDOWS) + + # + # Windows host (not used in cross compiling with mingw on Linux) + # + contains(QMAKE_HOST.os, Windows): { + contains(QMAKE_HOST.version, 192): { + # + # Windows 10 Universal CRT + # + UCRT_INCLUDE = "C:/Program Files (x86)/Windows Kits/10/include/10.0.10240.0/ucrt" + UCRT_LIBS = "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.10240.0/ucrt" + + INCLUDEPATH += $$UCRT_INCLUDE + + contains(QMAKE_TARGET.arch, x86_64) { + CONFIG(debug, debug|release) { + LIBS += $$UCRT_LIBS"/x64/ucrtd.lib" + } else { + LIBS += $$UCRT_LIBS"/x64/ucrt.lib" + } + } else { + CONFIG(debug, debug|release) { + LIBS += $$UCRT_LIBS"/x86/ucrtd.lib" + } else { + LIBS += $$UCRT_LIBS"/x86/ucrt.lib" + } + } + } + } +} +unix:macx: { + QMAKE_LFLAGS += -framework IOKit -framework Foundation + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 + + LIBS += -dead_strip +} + +# +# Git version getters +# +win32: { + contains(QMAKE_HOST.os, Windows): { + # + # Host is Windows + # + GIT = ""C:\\Progra~1\\Git\\bin\\git.exe"" + } + else { + # + # Host is Linux, cross compiling with mingw + # + GIT = git + } +} +unix:GIT = git + +# +# Define the app version strings +# +BUILD_NUMBER = $$system($$GIT rev-list --count HEAD) +GIT_HASH = $$system($$GIT rev-parse HEAD) +GIT_BRANCH = $$system($$GIT rev-parse --abbrev-ref HEAD) + +GIT_VERSION_LONG = $$system($$GIT describe --long) +GIT_VERSION = $$section(GIT_VERSION_LONG, -, 0, 0) + +VERSION_MAJOR = $$section(GIT_VERSION, ., 0, 0) +VERSION_MINOR = $$section(GIT_VERSION, ., 1, 1) +VERSION_PATCH = $$section(GIT_VERSION, ., 2, 2) + +DEFINES += APP_VERSION_MAJOR=\\\"$$VERSION_MAJOR\\\" +DEFINES += APP_VERSION_MINOR=\\\"$$VERSION_MINOR\\\" +DEFINES += APP_VERSION_PATCH=\\\"$$VERSION_PATCH\\\" +DEFINES += APP_BUILD=\\\"$$BUILD_NUMBER\\\" +DEFINES += APP_GITHASH=\\\"$$GIT_HASH\\\" +DEFINES += APP_GITBRANCH=\\\"$$GIT_BRANCH\\\" + +message("Buildnumber: "$$BUILD_NUMBER) +message("Git hash: "$$GIT_HASH) +message("Git branch: "$$GIT_BRANCH) +message("Version: "$$VERSION_MAJOR"."$$VERSION_MINOR"."$$VERSION_PATCH) +#message($$QMAKESPEC) + + +# +# DO NOT COMPRESS THE RESOURCES. QFile.map() cannot handle it... +# +#QMAKE_RESOURCE_FLAGS += -no-compress + + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + systrayxlink.cpp + +HEADERS += \ + mainwindow.h \ + systrayxlink.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + + +RESOURCES += \ + SysTray-X.qrc + +win32:RC_FILE += \ + SysTray-X.rc + +# +# Needs to be at the end of the .pro file (bug in qmake?) +# +unix:macx: { + # + # Use custom plist + # + QMAKE_INFO_PLIST = files/mac/SysTrayXInfo.plist + + # + # Set company name + # + QMAKE_TARGET_BUNDLE_PREFIX = Ximi1970. + + # + # Set icon + # + ICON = files/mac/SysTray-X.icns + + # + # Set version + # + VERSION = "$$VERSION_MAJOR"."$$VERSION_MINOR"."$$VERSION_PATCH" + VERSION_LONG = "$$VERSION_MAJOR"."$$VERSION_MINOR"."$$VERSION_PATCH" "$$LITERAL_HASH$$BUILD_NUMBER" - "$$GIT_HASH" - "$$GIT_BRANCH" + + QMAKE_POST_LINK = /usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString $${VERSION}\" $${OUT_PWD}/$${TARGET}.app/Contents/Info.plist ; + QMAKE_POST_LINK += /usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $${VERSION_LONG}\" $${OUT_PWD}/$${TARGET}.app/Contents/Info.plist ; + + # + # Add license file + # + APP_LICENSE_FILES.files = files/mac/LICENSE + APP_LICENSE_FILES.path = Contents/SharedSupport + QMAKE_BUNDLE_DATA += APP_LICENSE_FILES + + # + # Create and use internal frameworks + # + QMAKE_LFLAGS += '-Wl,-rpath,\'@executable_path/../Frameworks\'' + + QMAKE_POST_LINK += rm -rf $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks ; + QMAKE_POST_LINK += mkdir -p $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks ; + + QMAKE_POST_LINK += cp -R $$[QT_INSTALL_LIBS]/QtCore.framework $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks ; + QMAKE_POST_LINK += cp -R $$[QT_INSTALL_LIBS]/QtGui.framework $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks ; +} diff --git a/app/SysTray-X/SysTray-X.qrc b/app/SysTray-X/SysTray-X.qrc new file mode 100644 index 0000000..6fafe49 --- /dev/null +++ b/app/SysTray-X/SysTray-X.qrc @@ -0,0 +1,5 @@ + + + files/icons/SysTray-X.png + + diff --git a/app/SysTray-X/SysTray-X.rc b/app/SysTray-X/SysTray-X.rc new file mode 100644 index 0000000..387147f --- /dev/null +++ b/app/SysTray-X/SysTray-X.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "files/icons/SysTray-X.ico" diff --git a/app/SysTray-X/files/icons/LICENSE b/app/SysTray-X/files/icons/LICENSE new file mode 100644 index 0000000..c4e7bdc --- /dev/null +++ b/app/SysTray-X/files/icons/LICENSE @@ -0,0 +1 @@ +The icon used here is taken from the "Miscellany Web icons" set by Maria & Guillem (https://www.iconfinder.com/andromina), and is used under the Creative Commons (Attribution 3.0 Unported) license. diff --git a/app/SysTray-X/files/icons/SysTray-X.png b/app/SysTray-X/files/icons/SysTray-X.png new file mode 100644 index 0000000..e36321c Binary files /dev/null and b/app/SysTray-X/files/icons/SysTray-X.png differ diff --git a/app/SysTray-X/main.cpp b/app/SysTray-X/main.cpp new file mode 100644 index 0000000..b48f94e --- /dev/null +++ b/app/SysTray-X/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/app/SysTray-X/mainwindow.cpp b/app/SysTray-X/mainwindow.cpp new file mode 100644 index 0000000..b4e8bc6 --- /dev/null +++ b/app/SysTray-X/mainwindow.cpp @@ -0,0 +1,38 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + connect( &m_systray_x_link, &SysTrayXLink::signalReceivedMessageLength, this, &MainWindow::slotReceivedMessageLength ); + connect( &m_systray_x_link, &SysTrayXLink::signalReceivedMessage, this, &MainWindow::slotReceivedMessage ); + + connect( this, &MainWindow::signalWriteMessage, &m_systray_x_link, &SysTrayXLink::slotLinkWrite ); +} + + +MainWindow::~MainWindow() +{ + delete ui; +} + + +void MainWindow::slotReceivedMessageLength( qint32 msglen ) +{ + ui->label_length->setText(QString::number( msglen ) ); +} + + +void MainWindow::slotReceivedMessage( QByteArray message ) +{ + ui->label_message->setText( QString::fromStdString( message.toStdString() ) ); + + /* + * Reply + */ + QByteArray reply = QString( "\"Hallo other world!\"" ).toUtf8(); + emit signalWriteMessage( reply ); +} diff --git a/app/SysTray-X/mainwindow.h b/app/SysTray-X/mainwindow.h new file mode 100644 index 0000000..6dd3ed0 --- /dev/null +++ b/app/SysTray-X/mainwindow.h @@ -0,0 +1,60 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +/* + * Local includes + */ +#include "systrayxlink.h" + +/* + * Qt includes + */ +#include +#include + + + +namespace Ui { + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + + public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + + private slots: + + /** + * @brief slotReceivedMessageLength + * + * @param msglen + */ + void slotReceivedMessageLength( qint32 msglen ); + + /** + * @brief slotReceivedMessage + * + * @param message + */ + void slotReceivedMessage( QByteArray message ); + + signals: + + /** + * @brief signalWriteMessage + * + * @param message + */ + void signalWriteMessage( QByteArray message ); + + private: + Ui::MainWindow *ui; + + SysTrayXLink m_systray_x_link; +}; + +#endif // MAINWINDOW_H diff --git a/app/SysTray-X/mainwindow.ui b/app/SysTray-X/mainwindow.ui new file mode 100644 index 0000000..148e884 --- /dev/null +++ b/app/SysTray-X/mainwindow.ui @@ -0,0 +1,67 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + 50 + 10 + 271 + 51 + + + + Data here + + + + + + 50 + 80 + 271 + 51 + + + + Data here + + + + + + + 0 + 0 + 400 + 30 + + + + + + TopToolBarArea + + + false + + + + + + + + diff --git a/app/SysTray-X/systrayxlink.cpp b/app/SysTray-X/systrayxlink.cpp new file mode 100644 index 0000000..098aaf5 --- /dev/null +++ b/app/SysTray-X/systrayxlink.cpp @@ -0,0 +1,142 @@ +#include "systrayxlink.h" + +/* + * Local includes + */ +#include + +/* + * Qt includes + */ +#include +#include +#include + + +/* + * Constructor + */ +SysTrayXLink::SysTrayXLink() +{ + /* + * Open stdin + */ + m_stdin = new QFile( this ); + m_stdin->open( stdin, QIODevice::ReadOnly ); + + /* + * Open stdout + */ + m_stdout = new QFile( this ); + m_stdout->open( stdout, QIODevice::WriteOnly ); + + /* + * Setup the notifiers + */ + m_notifierLinkRead = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Read, this ); + connect( m_notifierLinkRead, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkRead ); + + m_notifierLinkReadException = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Exception, this ); + connect( m_notifierLinkReadException, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkReadException ); + + + QDataStream out( m_stdout ); + + char reply[] = "\"Hallo other World!\""; + qint32 replylen = sizeof( reply ) - 1; + + + out.writeRawData( reinterpret_cast< char* >( &replylen ), sizeof( qint32 ) ); + out.writeRawData( reply, replylen ); + +} + + +/* + * Destructor + */ +SysTrayXLink::~SysTrayXLink() +{ + /* + * Cleanup + */ + m_stdin->close(); + delete m_stdin; + + m_stdout->close(); + delete m_stdout; + + delete m_notifierLinkRead; + delete m_notifierLinkReadException; +} + + +/* + * Read the input + */ +void SysTrayXLink::slotLinkRead() +{ + QDataStream in( m_stdin ); + + qint32 msglen; + int status1 = in.readRawData( reinterpret_cast< char* >( &msglen ), sizeof( qint32 ) ); + + emit signalReceivedMessageLength(msglen); + + QByteArray message(msglen + 1, 0 ); + int status2 = in.readRawData( message.data(), msglen ); + + emit signalReceivedMessage( message ); + + if( ( status1 == 4 ) && ( status2 == msglen ) ) + { + //dummy + } + +/* + QDataStream out( m_stdout ); + + char reply[] = "\"Hallo other World!\""; + qint32 replylen = sizeof( reply ) - 1; + + int status3 = out.writeRawData( reinterpret_cast< char* >( &replylen ), sizeof( qint32 ) ); + int status4 = out.writeRawData( reply, replylen ); + m_stdout->flush(); + + if( status3 && status4 ) + { + //dummy + } +*/ +} + + +/* + * Handle notifier exception + */ +void SysTrayXLink::slotLinkReadException() +{ + // Something went wrong +} + + + + +/* + * Read the input + */ +void SysTrayXLink::slotLinkWrite( QByteArray message ) +{ + QDataStream out( m_stdout ); + + qint32 msglen = message.length(); + int status1 = out.writeRawData( reinterpret_cast< char* >( &msglen ), sizeof( qint32 ) ); + int status2 = out.writeRawData( message.data(), msglen ); + + m_stdout->flush(); + + if( status1 && status2 ) + { +//dummy + } +} diff --git a/app/SysTray-X/systrayxlink.h b/app/SysTray-X/systrayxlink.h new file mode 100644 index 0000000..bca2efa --- /dev/null +++ b/app/SysTray-X/systrayxlink.h @@ -0,0 +1,92 @@ +#ifndef SYSTRAYXLINK_H +#define SYSTRAYXLINK_H + +/* + * Local includes + */ + +/* + * Qt includes + */ +#include + +/* + * Predefines + */ +class QFile; +class QSocketNotifier; + +/** + * @brief The SysTrayXLink class. Handles the communications link. + */ +class SysTrayXLink : public QObject +{ + Q_OBJECT + + public: + + /** + * @brief SysTrayXLink. Constructor, destructor. + */ + SysTrayXLink(); + ~SysTrayXLink(); + + public slots: + + /** + * @brief slotLinkWrite. Write the link. + */ + void slotLinkWrite( QByteArray message ); + + private slots: + + /** + * @brief slotLinkRead. Read the link. + */ + void slotLinkRead(); + + /** + * @brief slotLinkReadException. Handle a read link exception. + */ + void slotLinkReadException(); + + signals: + + /** + * @brief signalReceivedMessageLength + * + * @param msglen + */ + void signalReceivedMessageLength(qint32 msglen); + + /** + * @brief signalReceivedMessage + * + * @param message + */ + void signalReceivedMessage(QByteArray message); + + private: + + /** + * @brief m_stdin. Pointer to stdin file. + */ + QFile *m_stdin; + + /** + * @brief m_stdin. Pointer to stdout file. + */ + QFile *m_stdout; + + /** + * @brief m_notifierLinkRead. Pointers to the link read data notifier. + */ + QSocketNotifier *m_notifierLinkRead; + + /** + * @brief m_notifierLinkReadException. Pointers to the link read exception notifier. + */ + QSocketNotifier *m_notifierLinkReadException; +}; + +#endif // SYSTRAYXLINK_H diff --git a/app/SysTray_X.json b/app/SysTray_X.json new file mode 100644 index 0000000..52fe8d3 --- /dev/null +++ b/app/SysTray_X.json @@ -0,0 +1,7 @@ + { + "name": "SysTray_X", + "description": "SysTray-X System Tray App", + "path": "/path/to/native-messaging/app/SysTray-X", + "type": "stdio", + "allowed_extensions": [ "systray-x@Ximi1970" ] +} diff --git a/app/install-linux.sh b/app/install-linux.sh deleted file mode 100755 index 12041f4..0000000 --- a/app/install-linux.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -if [ -z $1 ] ; then - echo "Usage: $0 " - exit 1 -fi - -mkdir .mozilla/native-messaging-hosts -#mkdir .mozilla/managed-storage -#mkdir .mozilla/pkcs11-modules - -cp ping_pong.json .mozilla/native-messaging-hosts/ping_pong.json -#cp ping_pong.json .mozilla/managed-storage/ping_pong.json -#cp ping_pong.json .mozilla/pkcs11-modules/ping_pong.json diff --git a/app/ping_pong.json b/app/ping_pong.json index 46b933b..3d3bf52 100644 --- a/app/ping_pong.json +++ b/app/ping_pong.json @@ -1,7 +1,7 @@ { "name": "ping_pong", "description": "Example host for native messaging", - "path": "/home/maxime/Diskstation/github/Ximi1970/systray-x/app/ping_pong.py", + "path": "/path/to/native-messaging/app/ping_pong.py", "type": "stdio", "allowed_extensions": [ "systray-x@Ximi1970" ] } diff --git a/app/ping_pong.py b/app/ping_pong.py index d31ee49..2bf49c3 100755 --- a/app/ping_pong.py +++ b/app/ping_pong.py @@ -57,6 +57,7 @@ except AttributeError: sys.stdout.flush() while True: + sendMessage(encodeMessage("pong2")) receivedMessage = getMessage() if receivedMessage == "ping": sendMessage(encodeMessage("pong2")) diff --git a/webext/background.js b/webext/background.js index b5f376c..3d4adef 100644 --- a/webext/background.js +++ b/webext/background.js @@ -73,7 +73,7 @@ SysTrayX.Messaging = { filtersDiv.setAttribute("data-filters", JSON.stringify(filters)); }, - onGetAccountsStoageError: function(error) { + onGetAccountsStorageError: function(error) { console.log(`GetAccounts Error: ${error}`); }, @@ -81,7 +81,7 @@ SysTrayX.Messaging = { console.debug("Get accounts"); let getter = browser.storage.sync.get(["accounts", "filters"]); - getter.then(this.getAccountsStorage, this.onGetAccountsStoageError); + getter.then(this.getAccountsStorage, this.onGetAccountsStorageError); if (SysTrayX.debugAccounts) { let accountsDiv = document.getElementById("accounts"); @@ -92,21 +92,20 @@ SysTrayX.Messaging = { let accounts = JSON.parse(accountsAttr); console.debug("Accounts poll: " + accounts.length); } - }, + } }; console.log("Starting SysTray-X"); SysTrayX.Messaging.init(); - /* - * Start native messaging + * Start native messaging ping pong */ var port = browser.runtime.connectNative("ping_pong"); // Listen for messages from the app. -port.onMessage.addListener((response) => { +port.onMessage.addListener(response => { console.log("Received: " + response); }); @@ -118,6 +117,24 @@ function ping() { window.setInterval(ping, 1000); +/* + * Start native messaging SysTray-X + */ +var portSysTrayX = browser.runtime.connectNative("SysTray_X"); + +// Listen for messages from the app. +portSysTrayX.onMessage.addListener(response => { + console.log("Received: " + response); +}); + +// Every second, send the app a message. +function postSysTrayXMessage() { + console.log("Sending: Hallo World!"); + portSysTrayX.postMessage("Hallo World!"); +// portSysTrayX.postMessage({ key: "Hallo", value: "World!" }); +} + +window.setInterval(postSysTrayXMessage, 1000); /* * Poll the accounts