Skip to content

WebUI: Add option to display tracker icons #22907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

userwiths
Copy link
Contributor

@userwiths userwiths commented Jun 23, 2025

Closes #18982.

Summary of issue

QT app has a setting (turned ON by default) which downloads (into /tmp) the favicons of the trackers. This feature is missing from the WebUI where every trackes uses the same default svg.

Summary of Changes

Previously the setting was loaded only for MainWindow, unlike other preferences that are saved/loaded from the preference.* files. I've created the required methods in preference.* and removed the other ones used before.

This in turn allows us to expose this preference to the WebUI.

After that we apply a similar logic to the C++ retrieval, as we remove the "subdomain" (tracker.) and create an img element with the supposed favicon address. To the img we attach a onerror handler in order to be able to add the default svg if the fetch fails.

Can this be made only for WebUI and not change server code ?

Sure, im lost as to which preferences we expose from server and which we have only in WebUI. So if you think it should not alter the server code it can be done.

Notes

Change in CSP

img: https: was added to the CSP, in case you think it might expose some/any security issues. Hopefully the nosniff will not allow the icon to be interpreted as anything other than an image.

Images might take a second to load

I notice a lag on the first opening of WebUI, the page is responsive and all but the lag is that the trackers need a few seconds in order to populate with either their favicons or the default svg.
(picture element from HTML5 had support for multiple sources 🤔 )

My vision of best approach

It crossed my mind that all the info about the trackers could be passed back to the WebUI with the same request that loads the trackers, but after seeing that the downloaded image file gets assigned to a QT object I got kinda discouraged. Not sure how to map icon to tracker in this implementation. In any case, if you think changing some of the core logic in order to allow the tracker to have its own icon (not bound to a QListWidgetItem) im willing to look into it.

@glassez
Copy link
Member

glassez commented Jun 23, 2025

It crossed my mind that all the info about the trackers could be passed back to the WebUI with the same request that loads the trackers, but after seeing that the downloaded image file gets assigned to a QT object I got kinda discouraged.

qBittorrent core doesn't care about all these icons because it have nothing to do with them. It's pure UI feature thus it is implemented at appropriate layer of qBittorrent desktop app. IMO, there is no enough reason to change this architecture. If some another UI (e.g. official or third party WebUI) want the similar feature they can be implemented there at their own.
As for the settings. It's illogical to store settings on the server that have no impact on the server itself.

@userwiths
Copy link
Contributor Author

This exact setting impacts both the WebUI and the QT app.
The difference is in the implementation, as the QT App was loading it in the constructor of MainWindow till now.

So my take from your comment is that this setting is supposed to be present both in WebUI and App at the same time

As for the "core" question, sure, i understand your point. Wont be chasing such changes and stick to the simplest possible WebUI implementation of this feature.

@glassez
Copy link
Member

glassez commented Jun 23, 2025

So my take from your comment is that this setting is supposed to be present both in WebUI and App at the same time

No. You didn't get me.
Currently this setting only affects desktop app UI. It is incorrect to reuse it in the WebUI, as it does not guarantee that any specific (3rd party) WebUI will have the corresponding feature. Additionally, it creates an incorrect dependency by moving this pure UI setting to the core layer. (Historically, qBittorrent handle all settings in a single way, although I've been planning to put things in their proper places for a long time.)

@Piccirello
Copy link
Member

So my take from your comment is that this setting is supposed to be present both in WebUI and App at the same time

No. You didn't get me. Currently this setting only affects desktop app UI. It is incorrect to reuse it in the WebUI, as it does not guarantee that any specific (3rd party) WebUI will have the corresponding feature. Additionally, it creates an incorrect dependency by moving this pure UI setting to the core layer. (Historically, qBittorrent handle all settings in a single way, although I've been planning to put things in their proper places for a long time.)

I see your point, but I also think it would be nonsensical to add this feature without having the server persist the setting. It can remain separate from the existing desktop app UI preference. I know you've had similar objections to persisting other WebUI preferences on the server. For better or worse, the WebUI is a core part of qBittorrent, and there are no immediate plans to separate them (whenever the idea comes up, it is heavily pushed back on, including by me. If we had any sort of telemetry, it would be interesting to see the breakdown of GUI usage vs WebUI usage - though to be clear I'm not proposing we add telemetry).

Perhaps you would feel better if we had a new API that was exclusively used for persisting WebUI-related behavior preferences? For a WebUI user, it is a really poor experience to have these settings reset each time local storage is cleared or you access the WebUI from a different browser. I know you will have strong opinions about this API, so you can help design its architecture.

@glassez glassez changed the title WebUI: Add tracker icons WebUI: Add option to display tracker icons Jun 24, 2025
@glassez
Copy link
Member

glassez commented Jun 24, 2025

For better or worse, the WebUI is a core part of qBittorrent

WebAPI - yes. WebUI - no, despite the fact that one of them is "official", its source code is hosted in the main qBittorrent repository, and it is shipped with qBittorrent binary. It is still separate client application.

For a WebUI user, it is a really poor experience to have these settings reset each time local storage is cleared or you access the WebUI from a different browser.

It sounds reasonable enough.
Indeed, to improve this, qBittorrent could provide some kind of storage service for such settings. However, I don't think it's appropriate to make it dependent on these settings themselves, as they come from a higher level than the WebAPI.
I could imagine it as an abstract service that allows the client to store and retrieve arbitrary data in key=value format. This would allow the WebUI to store its (exclusive) settings without creating incorrect dependencies between Core and UI layers.

: u"default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self'; frame-src 'self' blob:;"_s)
: u"default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self'; frame-src 'self' blob:;"_s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not too much trouble, can the CSP only be altered when the favicon feature is enabled?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not too much trouble, can the CSP only be altered when the favicon feature is enabled?

It is impossible unless "tracker favicons" feature is really considered as a core feature of qBittorrent so that you can check for corresponding setting at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Headers are setup on each request rather than once on "boot", so ....

We could (possible, but a bad idea probably), if we grab onto something like a cookie and add https only if it exists.

Not saying thats a good idea but its possible. If there is another more secure way to pass info in the m_request variable we could use a similar approach.

That would also allow us to separate the WebUI option and the QT setting as discussed imo.

@@ -654,6 +656,19 @@ Http::Response WebApplication::processRequest(const Http::Request &request, cons
         print((!error.message().isEmpty() ? error.message() : error.statusText()), Http::CONTENT_TYPE_TXT);
     }
 
+    const QString showTrackerIconCookie {parseCookie(m_request.headers.value(u"cookie"_s)).value(u"show_tracker_icon_enabled"_s)};
+    if (showTrackerIconCookie.compare(u"true"_s, Qt::CaseInsensitive) == 0)
+    {
+        for (auto &header : m_prebuiltHeaders)
+        {
+            if (header.name == Http::HEADER_CONTENT_SECURITY_POLICY)
+            {
+                header.value.replace(u" img-src 'self' data:"_s, u" img-src 'self' data: https:"_s);
+                break;
+            }
+        }
+    }
+
     for (const Http::Header &prebuiltHeader : asConst(m_prebuiltHeaders))
         setHeader(prebuiltHeader);

@@ -702,6 +702,18 @@ window.addEventListener("DOMContentLoaded", (event) => {
case TRACKERS_WARNING:
span.lastElementChild.src = "images/tracker-warning.svg";
break;
default: {
if (LocalPreferences.get("show_tracker_favicon", "true") === "false")
Copy link
Member

@Piccirello Piccirello Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change results in the WebUI making requests to external services, which it currently doesn't do at all. Given this I think it'd be preferable if this feature were to default to disabled, rather than enabled.

@xavier2k6 xavier2k6 added the WebUI WebUI-related issues/changes label Jun 25, 2025
const img = trackerFilterItem.getElementsByTagName("img")[0];

img.src = `https://${link}/favicon.ico`;
img.onerror = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set referrerPolicy to same-origin might be a good idea.

ref: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/referrerPolicy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are non-public clients, I'd even opt for no-referrer.

if (LocalPreferences.get("show_tracker_favicon", "true") === "false")
break;
const link = host.split(".").slice(1).join(".");
const img = trackerFilterItem.getElementsByTagName("img")[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a random idea. Is it possible to use an iframe instead of img? and sandbox it properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems sites dont want to be embedded without their consent

https://support.mozilla.org/en-US/kb/xframe-neterror-page

For example https://www.kali.org/images/favicon.ico returns with X-Frame-Options: SAMEORIGIN header that does not allow the iframe to display it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work:

<iframe sandbox srcdoc="<img src=&quot;https://www.kali.org/images/favicon.ico&quot;>"></iframe>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WebUI WebUI-related issues/changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WebUI: Add tracker favicon in Qbittorrent filters
6 participants