mirror of
https://github.com/cmclark00/retro-imager.git
synced 2025-05-18 07:55:21 +01:00
Enable telemetry
- Phone back home image downloaded for image popularity research. Only in case image comes from our repository (NOT for custom images)
This commit is contained in:
parent
f6a8c4d943
commit
95ce718d41
9 changed files with 111 additions and 9 deletions
|
@ -20,7 +20,7 @@ set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
# Adding headers explicity so they are displayed in Qt Creator
|
# Adding headers explicity so they are displayed in Qt Creator
|
||||||
set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelistitem.h drivelistmodel.h drivelistmodelpollthread.h driveformatthread.h powersaveblocker.h
|
set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelistitem.h drivelistmodel.h drivelistmodelpollthread.h driveformatthread.h powersaveblocker.h
|
||||||
downloadthread.h downloadextractthread.h localfileextractthread.h dependencies/mountutils/src/mountutils.hpp)
|
downloadthread.h downloadextractthread.h localfileextractthread.h downloadstatstelemetry.h dependencies/mountutils/src/mountutils.hpp)
|
||||||
|
|
||||||
# Add dependencies
|
# Add dependencies
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
@ -68,7 +68,7 @@ endif()
|
||||||
|
|
||||||
set(SOURCES "main.cpp" "imagewriter.cpp" "networkaccessmanagerfactory.cpp"
|
set(SOURCES "main.cpp" "imagewriter.cpp" "networkaccessmanagerfactory.cpp"
|
||||||
"drivelistitem.cpp" "drivelistmodel.cpp" "drivelistmodelpollthread.cpp" "downloadthread.cpp" "downloadextractthread.cpp"
|
"drivelistitem.cpp" "drivelistmodel.cpp" "drivelistmodelpollthread.cpp" "downloadthread.cpp" "downloadextractthread.cpp"
|
||||||
"driveformatthread.cpp" "localfileextractthread.cpp" "powersaveblocker.cpp" "qml.qrc")
|
"driveformatthread.cpp" "localfileextractthread.cpp" "powersaveblocker.cpp" "downloadstatstelemetry.cpp" "qml.qrc")
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Core Quick LinguistTools Svg OPTIONAL_COMPONENTS Widgets)
|
find_package(Qt5 COMPONENTS Core Quick LinguistTools Svg OPTIONAL_COMPONENTS Widgets)
|
||||||
if (Qt5Widgets_FOUND)
|
if (Qt5Widgets_FOUND)
|
||||||
|
|
8
config.h
8
config.h
|
@ -8,10 +8,14 @@
|
||||||
|
|
||||||
|
|
||||||
/* Repository URL */
|
/* Repository URL */
|
||||||
#define OSLIST_URL "https://downloads.raspberrypi.org/os_list_imagingutility.json"
|
#define OSLIST_URL "https://downloads.raspberrypi.org/os_list_imagingutility_v2.json"
|
||||||
|
|
||||||
/* Time synchronization URL (only used on eglfs QPA platform, URL must be HTTP) */
|
/* Time synchronization URL (only used on eglfs QPA platform, URL must be HTTP) */
|
||||||
#define TIME_URL "http://downloads.raspberrypi.org/os_list_imagingutility.json?time_synchronization"
|
#define TIME_URL "http://downloads.raspberrypi.org/os_list_imagingutility_v2.json?time_synchronization"
|
||||||
|
|
||||||
|
/* Phone home the name of images downloaded for image popularity ranking */
|
||||||
|
#define TELEMETRY_URL "https://rpi-imager-stats.raspberrypi.org/downloads?url=$imageurl&os=$parentcategory&image=$osname"
|
||||||
|
#define TELEMETRY_ENABLED_DEFAULT true
|
||||||
|
|
||||||
/* Hash algorithm for verifying (uncompressed image) checksum */
|
/* Hash algorithm for verifying (uncompressed image) checksum */
|
||||||
#define OSLIST_HASH_ALGORITHM QCryptographicHash::Sha256
|
#define OSLIST_HASH_ALGORITHM QCryptographicHash::Sha256
|
||||||
|
|
2
debian/changelog
vendored
2
debian/changelog
vendored
|
@ -8,6 +8,8 @@ rpi-imager (1.5) unstable; urgency=medium
|
||||||
* Add update notification support
|
* Add update notification support
|
||||||
* Allow translators to specify external .qm file for testing
|
* Allow translators to specify external .qm file for testing
|
||||||
* Remove dependency on qml-module-qt-labs-settings
|
* Remove dependency on qml-module-qt-labs-settings
|
||||||
|
* Enables telemetry collecting information about which images from
|
||||||
|
repository are most popular
|
||||||
|
|
||||||
-- Floris Bos <bos@je-eigen-domein.nl> Tue, 24 Nov 2020 10:38:21 +0100
|
-- Floris Bos <bos@je-eigen-domein.nl> Tue, 24 Nov 2020 10:38:21 +0100
|
||||||
|
|
||||||
|
|
53
downloadstatstelemetry.cpp
Normal file
53
downloadstatstelemetry.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include "downloadstatstelemetry.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
|
||||||
|
*/
|
||||||
|
|
||||||
|
DownloadStatsTelemetry::DownloadStatsTelemetry(const QByteArray &url, const QByteArray &parentcategory, const QByteArray &osname, QObject *parent)
|
||||||
|
: QThread(parent)
|
||||||
|
{
|
||||||
|
_url = QByteArray(TELEMETRY_URL).replace("$imageurl", QUrl::toPercentEncoding(url)).replace("$parentcategory", QUrl::toPercentEncoding(parentcategory)).replace("$osname", QUrl::toPercentEncoding(osname));
|
||||||
|
_useragent = "Mozilla/5.0 rpi-imager/" IMAGER_VERSION_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadStatsTelemetry::run()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
if (!settings.value("telemetry", TELEMETRY_ENABLED_DEFAULT).toBool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_c = curl_easy_init();
|
||||||
|
curl_easy_setopt(_c, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(_c, CURLOPT_WRITEFUNCTION, &DownloadStatsTelemetry::_curl_write_callback);
|
||||||
|
curl_easy_setopt(_c, CURLOPT_HEADERFUNCTION, &DownloadStatsTelemetry::_curl_header_callback);
|
||||||
|
curl_easy_setopt(_c, CURLOPT_URL, _url.constData());
|
||||||
|
curl_easy_setopt(_c, CURLOPT_USERAGENT, _useragent.constData());
|
||||||
|
curl_easy_setopt(_c, CURLOPT_CONNECTTIMEOUT, 10);
|
||||||
|
curl_easy_setopt(_c, CURLOPT_LOW_SPEED_TIME, 10);
|
||||||
|
curl_easy_setopt(_c, CURLOPT_LOW_SPEED_LIMIT, 10);
|
||||||
|
|
||||||
|
CURLcode ret = curl_easy_perform(_c);
|
||||||
|
curl_easy_cleanup(_c);
|
||||||
|
|
||||||
|
qDebug() << "Telemetry done. cURL status code =" << ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* /dev/null write handler */
|
||||||
|
size_t DownloadStatsTelemetry::_curl_write_callback(char *, size_t size, size_t nmemb, void *)
|
||||||
|
{
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DownloadStatsTelemetry::_curl_header_callback( void *ptr, size_t size, size_t nmemb, void *)
|
||||||
|
{
|
||||||
|
int len = size*nmemb;
|
||||||
|
QByteArray headerstr((char *) ptr, len);
|
||||||
|
//qDebug() << "Received telemetry header:" << headerstr;
|
||||||
|
return len;
|
||||||
|
}
|
31
downloadstatstelemetry.h
Normal file
31
downloadstatstelemetry.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef DOWNLOADSTATSTELEMETRY_H
|
||||||
|
#define DOWNLOADSTATSTELEMETRY_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
class DownloadStatsTelemetry : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DownloadStatsTelemetry(const QByteArray &url, const QByteArray &parentcategory, const QByteArray &osname, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CURL *_c;
|
||||||
|
QByteArray _url, _useragent;
|
||||||
|
virtual void run();
|
||||||
|
static size_t _curl_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
||||||
|
static size_t _curl_header_callback( void *ptr, size_t size, size_t nmemb, void *userdata);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DOWNLOADSTATSTELEMETRY_H
|
|
@ -9,6 +9,7 @@
|
||||||
#include "dependencies/drivelist/src/drivelist.hpp"
|
#include "dependencies/drivelist/src/drivelist.hpp"
|
||||||
#include "driveformatthread.h"
|
#include "driveformatthread.h"
|
||||||
#include "localfileextractthread.h"
|
#include "localfileextractthread.h"
|
||||||
|
#include "downloadstatstelemetry.h"
|
||||||
#include <archive.h>
|
#include <archive.h>
|
||||||
#include <archive_entry.h>
|
#include <archive_entry.h>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
@ -112,13 +113,15 @@ void ImageWriter::setEngine(QQmlApplicationEngine *engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set URL to download from */
|
/* Set URL to download from */
|
||||||
void ImageWriter::setSrc(const QUrl &url, quint64 downloadLen, quint64 extrLen, QByteArray expectedHash, bool multifilesinzip)
|
void ImageWriter::setSrc(const QUrl &url, quint64 downloadLen, quint64 extrLen, QByteArray expectedHash, bool multifilesinzip, QString parentcategory, QString osname)
|
||||||
{
|
{
|
||||||
_src = url;
|
_src = url;
|
||||||
_downloadLen = downloadLen;
|
_downloadLen = downloadLen;
|
||||||
_extrLen = extrLen;
|
_extrLen = extrLen;
|
||||||
_expectedHash = expectedHash;
|
_expectedHash = expectedHash;
|
||||||
_multipleFilesInZip = multifilesinzip;
|
_multipleFilesInZip = multifilesinzip;
|
||||||
|
_parentCategory = parentcategory;
|
||||||
|
_osName = osname;
|
||||||
|
|
||||||
if (!_downloadLen && url.isLocalFile())
|
if (!_downloadLen && url.isLocalFile())
|
||||||
{
|
{
|
||||||
|
@ -191,6 +194,9 @@ void ImageWriter::startWrite()
|
||||||
else if (compressed)
|
else if (compressed)
|
||||||
{
|
{
|
||||||
_thread = new DownloadExtractThread(urlstr, _dst.toLatin1(), _expectedHash, this);
|
_thread = new DownloadExtractThread(urlstr, _dst.toLatin1(), _expectedHash, this);
|
||||||
|
DownloadStatsTelemetry *tele = new DownloadStatsTelemetry(urlstr, _parentCategory.toLatin1(), _osName.toLatin1(), this);
|
||||||
|
connect(tele, SIGNAL(finished()), tele, SLOT(deleteLater()));
|
||||||
|
tele->start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
void setEngine(QQmlApplicationEngine *engine);
|
void setEngine(QQmlApplicationEngine *engine);
|
||||||
|
|
||||||
/* Set URL to download from, and if known download length and uncompressed length */
|
/* Set URL to download from, and if known download length and uncompressed length */
|
||||||
Q_INVOKABLE void setSrc(const QUrl &url, quint64 downloadLen = 0, quint64 extrLen = 0, QByteArray expectedHash = "", bool multifilesinzip = false);
|
Q_INVOKABLE void setSrc(const QUrl &url, quint64 downloadLen = 0, quint64 extrLen = 0, QByteArray expectedHash = "", bool multifilesinzip = false, QString parentcategory = "", QString osname = "");
|
||||||
|
|
||||||
/* Set device to write to */
|
/* Set device to write to */
|
||||||
Q_INVOKABLE void setDst(const QString &device, quint64 deviceSize = 0);
|
Q_INVOKABLE void setDst(const QString &device, quint64 deviceSize = 0);
|
||||||
|
@ -120,7 +120,7 @@ protected slots:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUrl _src, _repo;
|
QUrl _src, _repo;
|
||||||
QString _dst, _cacheFileName;
|
QString _dst, _cacheFileName, _parentCategory, _osName;
|
||||||
QByteArray _expectedHash, _cachedFileHash;
|
QByteArray _expectedHash, _cachedFileHash;
|
||||||
quint64 _downloadLen, _extrLen, _devLen, _dlnow, _verifynow;
|
quint64 _downloadLen, _extrLen, _devLen, _dlnow, _verifynow;
|
||||||
DriveListModel _drivelist;
|
DriveListModel _drivelist;
|
||||||
|
|
|
@ -57,5 +57,7 @@
|
||||||
<releases>
|
<releases>
|
||||||
<release version="@IMAGER_VERSION_STR@" />
|
<release version="@IMAGER_VERSION_STR@" />
|
||||||
</releases>
|
</releases>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1">
|
||||||
|
<content_attribute id="social-info">moderate</content_attribute>
|
||||||
|
</content_rating>
|
||||||
</component>
|
</component>
|
||||||
|
|
6
main.qml
6
main.qml
|
@ -261,6 +261,7 @@ ApplicationWindow {
|
||||||
height: parent.height-50
|
height: parent.height-50
|
||||||
padding: 0
|
padding: 0
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
property string categorySelected : ""
|
||||||
|
|
||||||
// background of title
|
// background of title
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -936,13 +937,16 @@ ApplicationWindow {
|
||||||
else
|
else
|
||||||
suboslist.currentIndex = -1
|
suboslist.currentIndex = -1
|
||||||
osswipeview.setCurrentIndex(1)
|
osswipeview.setCurrentIndex(1)
|
||||||
|
ospopup.categorySelected = d.name
|
||||||
} else if (typeof(d.subitems_url) == "string" && d.subitems_url !== "") {
|
} else if (typeof(d.subitems_url) == "string" && d.subitems_url !== "") {
|
||||||
if (d.subitems_url === "internal://back")
|
if (d.subitems_url === "internal://back")
|
||||||
{
|
{
|
||||||
osswipeview.setCurrentIndex(0)
|
osswipeview.setCurrentIndex(0)
|
||||||
|
ospopup.categorySelected = ""
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ospopup.categorySelected = d.name
|
||||||
var suburl = d.subitems_url
|
var suburl = d.subitems_url
|
||||||
if (subosmodel.count>1)
|
if (subosmodel.count>1)
|
||||||
{
|
{
|
||||||
|
@ -994,7 +998,7 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imageWriter.setSrc(d.url, d.image_download_size, d.extract_size, typeof(d.extract_sha256) != "undefined" ? d.extract_sha256 : "", typeof(d.contains_multiple_files) != "undefined" ? d.contains_multiple_files : false)
|
imageWriter.setSrc(d.url, d.image_download_size, d.extract_size, typeof(d.extract_sha256) != "undefined" ? d.extract_sha256 : "", typeof(d.contains_multiple_files) != "undefined" ? d.contains_multiple_files : false, ospopup.categorySelected, d.name)
|
||||||
osbutton.text = d.name
|
osbutton.text = d.name
|
||||||
ospopup.close()
|
ospopup.close()
|
||||||
if (imageWriter.readyToWrite()) {
|
if (imageWriter.readyToWrite()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue