Chrome addon is randomly sending trash to my c++ native host application

给你一囗甜甜゛ 提交于 2020-03-23 08:22:32

问题


I'm trying to write a simple parental control app for my university project, but I'm a newbie in browser addons. I want to use Chrome addon to send hosts viewed by the user in real-time to Qt app, which will analyze the user behavior. The problem is, that sometimes chrome's sending a correct host, another time it's sending trash with an empty string or enormously long message, which my Qt app filter. But these 'wrong' messages are sent in an endless loop, and to make it working again, I have to restart extension or chrome or even whole PC.

Chrome addon manifest:

{
    "name": "AM Chrome addon",
    "version": "0.7",
    "description": "Get your activity supervised!",
    "background": {
        "scripts": [
            "background.js"
        ],
        "persistent": false
    },
    "permissions": [
        "tabs",
        "nativeMessaging",
        "background"
    ],
    "manifest_version": 2
}

Addon background.js file:

var current = undefined;
var port = null;
tryConnectagain();

function tryConnectagain() {
    port = chrome.runtime.connectNative('<Native host app-name>');
    port.onDisconnect.addListener(onDisconnect);
}

function onDisconnect() {
    port = null;
        console.log("last error: ", chrome.runtime.lastError.message);
        setTimeout(tryConnectagain, 1000);
}

function sendMessageToNativeApp(message) {
    if (port != null) port.postMessage({ message: message });
}

function newUrl(u) {
    if (u != undefined && !u.includes(current) && !u.includes("chrome-extension://") && u.includes('.')) {
        var u = new URL(u);
        var domain = u.hostname.replace("www.", "");
        if (domain != current) {
            current = domain;
            sendMessageToNativeApp(current);
            console.log(current);
        }
    }
    else if (current != "NotURL") {
        current = "NotURL";
        sendMessageToNativeApp(current);
        console.log(current);
    }
}

// Here I'm trying to intercept all URL change situations

chrome.tabs.onActivated.addListener(function (activeInfo) {
    chrome.tabs.get(activeInfo.tabId, function (tab) {
        if (tab.active && tab.highlighted) newUrl(tab.url);
    });
});

chrome.tabs.onAttached.addListener(function (tabId, attachInfo) {
    chrome.tabs.get(tabId, function (tab) {
        if (tab.active && tab.highlighted) newUrl(tab.url);
    });
});

chrome.tabs.onReplaced.addListener(function (addedTabId, removedTabId) {
    chrome.tabs.get(addedTabId, function (tab) {
        if (tab.active && tab.highlighted) newUrl(tab.url);
    });
});

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    if (changeInfo.url && tab.active && tab.highlighted) newUrl(changeInfo.url);
});

chrome.windows.onFocusChanged.addListener(function (windowId) {
    if (windowId > -1) {
        var getInfo = { populate: true, windowTypes: ['normal'] };
        chrome.windows.getLastFocused(getInfo, function (window) {
            for (var t = 0; t < window.tabs.length; t++) {
                if (window.tabs[t].active && window.tabs[t].highlighted) {
                    newUrl(window.tabs[t].url);
                    break;
                }
            }
        })
    }
});

Native host app manifest:

{
  "name": "<Native host app-name>",
  "description": "Hostname Identifier",
  "path": "<Hostname app Path>",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://<extension-ID>/"
  ]
}

And a fragment of c++ qt code that receive data from addon: addonmessagereceiver.h:

#ifndef ADDONMESSAGERECEIVER_H
#define ADDONMESSAGERECEIVER_H

#include <qthread.h>
#include <QJsonDocument>
#include <QJsonObject>

#include <iostream>
#include <string>

class AddonMessageReceiver : public QThread
{
    Q_OBJECT
public:
    void run();
signals:
    void UpdateMessage(const QString &);
};

#endif // ADDONMESSAGERECEIVER_H

addonmessagereceiver.cpp:

#include "addonmessagereceiver.h"
#include <qdebug.h>
using namespace std;

void AddonMessageReceiver::run()
{
    do{
        char nextMessageLen[4];
        cin.read(nextMessageLen, 4);
        unsigned long int messageLength = *reinterpret_cast<unsigned long int *>(nextMessageLen);
        qDebug() << messageLength << static_cast<int>(nextMessageLen[0]) << static_cast<int>(nextMessageLen[1]) << static_cast<int>(nextMessageLen[2]) << static_cast<int>(nextMessageLen[3]);
        if(messageLength<1024 && messageLength>1)
        {
            char *incomingMessage = new char[messageLength+1];
            memset(incomingMessage,'\0',messageLength+1);
            cin.read(incomingMessage, messageLength);
            QString message = QString::fromLatin1(incomingMessage);
            delete[] incomingMessage;
            qDebug() << messageLength << message;
            if(message.length()>5)
            {
                QJsonDocument json = QJsonDocument::fromJson(message.toLatin1());
                QJsonObject obj = json.object();
                QString host = obj.value("message").toString();
                emit UpdateMessage(host);
            }
        }
        QThread::msleep(100);
    }while(true);
}

Example of qDebug wrong nextMessageLen in loop:

And an example of good input that turns into wrong in a loop:

Can you please tell me what is going on with that extension or chrome, or what I f... up with native app? Thank you for your answer.


回答1:


Based on this answer I have built a class that monitors "stdin", get the text and decode it using QFile:

nativemessenger.h

#ifndef NATIVEMESSENGER_H
#define NATIVEMESSENGER_H

#include <QObject>
#include <QFile>

class NativeMessenger : public QObject
{
    Q_OBJECT
public:
    explicit NativeMessenger(QObject *parent = nullptr);
public Q_SLOTS:
    void sendMessage(const QByteArray & message);
Q_SIGNALS:
    void messageChanged(const QByteArray & message);
private Q_SLOTS:
    void readyRead();
private:
    QFile m_qin;
    QFile m_qout;
};

#endif // NATIVEMESSENGER_H

nativemessenger.cpp

#include "nativemessenger.h"

#include <QCoreApplication>
#ifdef Q_OS_WIN
#include <QWinEventNotifier>
#include <windows.h>
#else
#include <QSocketNotifier>
#endif
NativeMessenger::NativeMessenger(QObject *parent) : QObject(parent)
{
#ifdef Q_OS_WIN
    // https://developer.chrome.com/apps/nativeMessaging#native-messaging-debugging
    _setmode(_fileno(stdin), _O_BINARY);
    _setmode(_fileno(stdout), _O_BINARY);
#endif

    m_qin.open(stdin, QIODevice::ReadOnly | QIODevice::Unbuffered);
    m_qout.open(stdout, QIODevice::WriteOnly);

#ifdef Q_OS_WIN
    QWinEventNotifier *m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
    connect(m_notifier, &QWinEventNotifier::activated, this, &NativeMessenger::readyRead);
#else
    QSocketNotifier *m_notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, this);
    connect(m_notifier, &QSocketNotifier::activated, this, &NativeMessenger::readyRead);
#endif
}

void NativeMessenger::sendMessage(const QByteArray &message){
    quint32 len = message.length();
    m_qout.write(reinterpret_cast<char *>(&len), sizeof(len));
    m_qout.write(message);
    m_qout.flush();
}

void NativeMessenger::readyRead(){
    m_qin.startTransaction();
    quint32 length = 0;
    qint64 rc = m_qin.read(reinterpret_cast<char *>(&length), sizeof(quint32));
    if (rc == -1) {
        m_qin.rollbackTransaction();
        return;
    }
    QByteArray message = m_qin.read(length);
    if (message.length() != int(length)) {
        m_qin.rollbackTransaction();
        return;
    }
    if (message.isEmpty()) {
        m_qin.rollbackTransaction();
        return;
    }
    m_qin.commitTransaction();
    Q_EMIT messageChanged(message);
}

main.cpp

#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>

#include <QDebug>

#include "nativemessenger.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    NativeMessenger listener;
    QObject::connect(&listener, &NativeMessenger::messageChanged,
                     [&listener]
                     (const QByteArray & message){
        // decode message 
        QJsonParseError error;
        QJsonDocument json = QJsonDocument::fromJson(message, &error);
        if(error.error != QJsonParseError::NoError){
            qDebug() << error.errorString();
        }
        // build response
        QJsonObject object
        {
            {"data", json.object()},
            {"name", QCoreApplication::applicationName()}
        };
        QByteArray response = QJsonDocument(object).toJson(QJsonDocument::Compact);
        // send response
        listener.sendMessage(response);
    });
    return a.exec();
}

A complete example can be found here.



来源:https://stackoverflow.com/questions/59336957/chrome-addon-is-randomly-sending-trash-to-my-c-native-host-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!