]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/widgets/PrivacyWebEngineView.cpp
Only display the HTTP Ping dialog if it originates from the current tab. https:...
[PrivacyBrowserPC.git] / src / widgets / PrivacyWebEngineView.cpp
1 /*
2  * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
5  *
6  * Privacy Browser PC is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser PC is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 // Application headers.
21 #include "PrivacyWebEngineView.h"
22 #include "Settings.h"
23 #include "databases/CookiesDatabase.h"
24 #include "databases/DomainsDatabase.h"
25 #include "interceptors/UrlRequestInterceptor.h"
26 #include "windows/BrowserWindow.h"
27
28 // Qt toolkit headers.
29 #include <QContextMenuEvent>
30 #include <QMenu>
31
32 // Construct the class.
33 PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr)
34 {
35     // Create an off-the-record profile (the default when no profile name is specified).
36     webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
37
38     // Create a WebEngine page.
39     QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
40
41     // Set the WebEngine page.
42     setPage(webEnginePagePointer);
43
44     // Get handles for the various aspects of the WebEngine.
45     webEngineSettingsPointer = webEnginePagePointer->settings();
46
47     // Instantiate the URL request interceptor.
48     UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
49
50     // Set the URL request interceptor.
51     webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
52
53     // Reapply the domain settings when the host changes.
54     connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(const QString&)), this, SLOT(applyDomainSettingsWithoutReloading(const QString&)));
55
56     // Display HTTP Ping blocked dialogs.
57     connect(urlRequestInterceptorPointer, SIGNAL(displayHttpPingDialog(const QString&)), this, SLOT(displayHttpPingDialog(const QString&)));
58 }
59
60 void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const
61 {
62     //qDebug() << "Add cookie:  " << cookie.toRawForm();
63
64     // Add the new cookie to the list.
65     cookieListPointer->push_front(cookie);
66
67     // Update the cookie if it is durable and has new data.
68     if (CookiesDatabase::isUpdate(cookie))
69         CookiesDatabase::updateCookie(cookie);
70
71     // Update the cookies action.
72     emit updateCookiesAction(cookieListPointer->size());
73 }
74
75 void PrivacyWebEngineView::applyDomainSettingsWithoutReloading(const QString &hostname)
76 {
77     // Apply the domain settings  `false` does not reload the website.
78     applyDomainSettings(hostname, false);
79 }
80
81 void PrivacyWebEngineView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
82 {
83     // Get the record for the hostname.
84     QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
85
86     // Check if the hostname has domain settings.
87     if (domainQuery.isValid())  // The hostname has domain settings.
88     {
89         // Get the domain record.
90         QSqlRecord domainRecord = domainQuery.record();
91
92         // Store the domain settings name.
93         domainSettingsName = domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString();
94
95         // Set the JavaScript status.
96         switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
97         {
98             // Set the default JavaScript status.
99             case (DomainsDatabase::SYSTEM_DEFAULT):
100             {
101                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
102
103                 break;
104             }
105
106             // Disable JavaScript.
107             case (DomainsDatabase::DISABLED):
108             {
109                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
110
111                 break;
112             }
113
114             // Enable JavaScript.
115             case (DomainsDatabase::ENABLED):
116             {
117                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
118
119                 break;
120             }
121         }
122
123         // Set the local storage status.
124         switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
125         {
126             // Set the default local storage status.
127             case (DomainsDatabase::SYSTEM_DEFAULT):
128             {
129                 localStorageEnabled = Settings::localStorageEnabled();
130
131                 break;
132             }
133
134             // Disable local storage.
135             case (DomainsDatabase::DISABLED):
136             {
137                 localStorageEnabled = false;
138
139                 break;
140             }
141
142             // Enable local storage.
143             case (DomainsDatabase::ENABLED):
144             {
145                 localStorageEnabled = true;
146
147                 break;
148             }
149         }
150
151         // Set the DOM storage status.
152         switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
153         {
154             // Set the default DOM storage status.  QWebEngineSettings confusingly calls this local storage.
155             case (DomainsDatabase::SYSTEM_DEFAULT):
156             {
157                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
158
159                 break;
160             }
161
162             // Disable DOM storage.  QWebEngineSettings confusingly calls this local storage.
163             case (DomainsDatabase::DISABLED):
164             {
165                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
166
167                 break;
168             }
169
170             // Enable DOM storage.  QWebEngineSettings confusingly calls this local storage.
171             case (DomainsDatabase::ENABLED):
172             {
173                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
174
175                 break;
176             }
177         }
178
179         // Set the user agent.
180         webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
181
182         // Check if a custom zoom factor is set.
183         if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
184         {
185             // Store the current zoom factor.
186             setZoomFactor(domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble());
187         }
188         else
189         {
190             // Reset the current zoom factor.
191             setZoomFactor(Settings::zoomFactor());
192         }
193     }
194     else  // The hostname does not have domain settings.
195     {
196         // Reset the domain settings name.
197         domainSettingsName = QLatin1String("");
198
199         // Set the JavaScript status.
200         webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
201
202         // Set the local storage status.
203         localStorageEnabled = Settings::localStorageEnabled();
204
205         // Set DOM storage.  In QWebEngineSettings it is called Local Storage.
206         webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
207
208         // Set the user agent.
209         webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
210
211         // Set the zoom factor.
212         setZoomFactor(Settings::zoomFactor());
213     }
214
215     // Reload the website if requested.
216     if (reloadWebsite)
217         reload();
218
219     // Update the UI.
220     emit updateUi(this);
221 }
222
223 void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) {
224     // Get a handle for the
225     QWebEnginePage *webEnginePagePointer = page();
226
227     // Get a handle for the menu.
228     QMenu *contextMenu = webEnginePagePointer->createStandardContextMenu();
229
230     // Get the list of context menu actions.
231     const QList<QAction *> contextMenuActionsList = contextMenu->actions();
232
233     // Add the open link in new background tab action if the context menu already contains the open link in new window action.
234     if (contextMenuActionsList.contains(webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow)))
235     {
236         // Move the open in new tab action to the top of the list.
237         contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewTab));
238
239         // Add the open link in background tab action below the open in new tab action.
240         contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewBackgroundTab));
241
242         // Move the open in new window action below the open in background tab action.
243         contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow));
244
245         // Add a separator below the open in new window action.
246         contextMenu->insertSeparator(webEnginePagePointer->action(QWebEnginePage::Back));
247     }
248
249     // Display the menu using the location in the context menu event.
250     contextMenu->popup(contextMenuEvent->globalPos());
251 }
252
253 QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType webWindowType) {
254     // Get a handle for the browser window.
255     BrowserWindow *browserWindowPointer = qobject_cast<BrowserWindow*>(window());
256
257     // Create the requested window type.
258     switch (webWindowType)
259     {
260         case QWebEnginePage::WebBrowserTab:
261         {
262             // Create the new tab and return the privacy WebEngine view pointer.  `true` removes the focus from the blank URL line edit.
263             // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
264             return browserWindowPointer->tabWidgetPointer->addTab(true);
265         }
266
267         case QWebEnginePage::WebBrowserWindow:
268         {
269             // Create a new browser window.
270             BrowserWindow *newBrowserWindowPointer = new BrowserWindow();
271
272             // Show the new browser window.
273             newBrowserWindowPointer->show();
274
275             // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
276             return newBrowserWindowPointer->tabWidgetPointer->loadBlankInitialWebsite();
277         }
278
279         case QWebEnginePage::WebBrowserBackgroundTab:
280         {
281             // Create the new tab and return the privacy WebEngine view pointer.  `false` does not clear the URL line edit.  `true` creates a background tab.
282             // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
283             return browserWindowPointer->tabWidgetPointer->addTab(false, true);
284         }
285
286         default:
287         {
288             // Return a null pointer for opening a web dialog.
289             return nullptr;
290         }
291     }
292 }
293
294 void PrivacyWebEngineView::displayHttpPingDialog(const QString &httpPingUrl) const
295 {
296     // Display the HTTP Ping blocked dialog.
297     emit displayHttpPingBlockedDialog(httpPingUrl);
298 }
299
300 void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
301 {
302     //qDebug() << "Remove cookie:  " << cookie.toRawForm();
303
304     // Remove the cookie from the list.
305     cookieListPointer->remove(cookie);
306
307     // Update the cookies action.
308     emit updateCookiesAction(cookieListPointer->size());
309 }