]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/widgets/PrivacyWebEngineView.cpp
Open new tabs adjacent to the current tab. https://redmine.stoutner.com/issues/1110
[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(QWidget *parentWidgetPointer) : QWebEngineView(parentWidgetPointer)
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(this);
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         // Store the domain settings name.
90         domainSettingsName = domainQuery.value(DomainsDatabase::DOMAIN_NAME).toString();
91
92         // Set the JavaScript status.
93         switch (domainQuery.value(DomainsDatabase::JAVASCRIPT).toInt())
94         {
95             // Set the default JavaScript status.
96             case (DomainsDatabase::SYSTEM_DEFAULT):
97             {
98                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
99
100                 break;
101             }
102
103             // Enable JavaScript.
104             case (DomainsDatabase::ENABLED):
105             {
106                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
107
108                 break;
109             }
110
111             // Disable JavaScript.
112             case (DomainsDatabase::DISABLED):
113             {
114                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
115
116                 break;
117             }
118         }
119
120         // Set the local storage status.
121         switch (domainQuery.value(DomainsDatabase::LOCAL_STORAGE).toInt())
122         {
123             // Set the default local storage status.
124             case (DomainsDatabase::SYSTEM_DEFAULT):
125             {
126                 localStorageEnabled = Settings::localStorageEnabled();
127
128                 break;
129             }
130
131             // Enable local storage.
132             case (DomainsDatabase::ENABLED):
133             {
134                 localStorageEnabled = true;
135
136                 break;
137             }
138
139             // Disable local storage.
140             case (DomainsDatabase::DISABLED):
141             {
142                 localStorageEnabled = false;
143
144                 break;
145             }
146         }
147
148         // Set the DOM storage status.
149         switch (domainQuery.value(DomainsDatabase::DOM_STORAGE).toInt())
150         {
151             // Set the default DOM storage status.  QWebEngineSettings confusingly calls this local storage.
152             case (DomainsDatabase::SYSTEM_DEFAULT):
153             {
154                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
155
156                 break;
157             }
158
159             // Enable DOM storage.  QWebEngineSettings confusingly calls this local storage.
160             case (DomainsDatabase::ENABLED):
161             {
162                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
163
164                 break;
165             }
166
167             // Disable DOM storage.  QWebEngineSettings confusingly calls this local storage.
168             case (DomainsDatabase::DISABLED):
169             {
170                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
171
172                 break;
173             }
174         }
175
176         // Set the user agent.
177         webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainQuery.value(DomainsDatabase::USER_AGENT).toString()));
178
179         // Check if a custom zoom factor is set.
180         if (domainQuery.value(DomainsDatabase::ZOOM_FACTOR).toInt())
181         {
182             // Store the current zoom factor.
183             defaultZoomFactor = domainQuery.value(DomainsDatabase::CUSTOM_ZOOM_FACTOR).toDouble();
184         }
185         else
186         {
187             // Store the current zoom factor.
188             defaultZoomFactor = Settings::zoomFactor();
189         }
190     }
191     else  // The hostname does not have domain settings.
192     {
193         // Reset the domain settings name.
194         domainSettingsName = QLatin1String("");
195
196         // Set the JavaScript status.
197         webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
198
199         // Set the local storage status.
200         localStorageEnabled = Settings::localStorageEnabled();
201
202         // Set DOM storage.  In QWebEngineSettings it is called Local Storage.
203         webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
204
205         // Set the user agent.
206         webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
207
208         // Store the zoom factor.
209         defaultZoomFactor = Settings::zoomFactor();
210     }
211
212     // Set the current zoom factor.
213     setZoomFactor(defaultZoomFactor);
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.  `true` adds the new tab adjacent to the current tab.
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, 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` adds the new tab adjacent to the current tab.
282             // `true` creates a background tab.
283             // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
284             return browserWindowPointer->tabWidgetPointer->addTab(false, true, true);
285         }
286
287         default:
288         {
289             // Return a null pointer for opening a web dialog.
290             return nullptr;
291         }
292     }
293 }
294
295 void PrivacyWebEngineView::displayHttpPingDialog(const QString &httpPingUrl) const
296 {
297     // Display the HTTP Ping blocked dialog.
298     emit displayHttpPingBlockedDialog(httpPingUrl);
299 }
300
301 void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
302 {
303     //qDebug() << "Remove cookie:  " << cookie.toRawForm();
304
305     // Remove the cookie from the list.
306     cookieListPointer->remove(cookie);
307
308     // Update the cookies action.
309     emit updateCookiesAction(cookieListPointer->size());
310 }