]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/MainView.cpp
Reapply domain settings when the host changes.
[PrivacyBrowserPC.git] / src / MainView.cpp
1 /*
2  * Copyright © 2022 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 "BrowserWindow.h"
22 #include "MainView.h"
23 #include "MouseEventFilter.h"
24 #include "Settings.h"
25 #include "ui_MainView.h"
26 #include "UrlRequestInterceptor.h"
27 #include "helpers/SearchEngineHelper.h"
28 #include "helpers/UserAgentHelper.h"
29
30 // Qt framework headers.
31 #include <QWebEngineProfile>
32
33 MainView::MainView(QWidget *parent) : QWidget(parent)
34 {
35     // Instantiate the mainview UI.
36     Ui::MainView mainViewUi;
37
38     // Setup the UI.
39     mainViewUi.setupUi(this);
40
41     // Get handles for the views.
42     backButtonPointer = mainViewUi.backButton;
43     forwardButtonPointer = mainViewUi.forwardButton;
44     QPushButton *refreshButtonPointer = mainViewUi.refreshButton;
45     QPushButton *homeButtonPointer = mainViewUi.homeButton;
46     urlLineEditPointer = mainViewUi.urlLineEdit;
47     javaScriptButtonPointer = mainViewUi.javaScript;
48     webEngineViewPointer = mainViewUi.webEngineView;
49
50     // Get handles for the aspects of the WebEngine.
51     QWebEnginePage *webEnginePagePointer = webEngineViewPointer->page();
52     webEngineHistoryPointer = webEnginePagePointer->history();
53     webEngineProfilePointer = webEnginePagePointer->profile();
54     webEngineSettingsPointer = webEngineViewPointer->settings();
55
56     // Update the webengine view from the URL line edit.
57     connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromTextBox(const QString)));
58
59     // Update the URL line edit form the webengine view.
60     connect(webEngineViewPointer, SIGNAL(loadStarted()), this, SLOT(updateInterface()));
61     connect(webEngineViewPointer, SIGNAL(loadProgress(const int)), this, SLOT(updateInterface()));
62     connect(webEngineViewPointer, SIGNAL(loadFinished(const bool)), this, SLOT(updateInterface()));
63
64     // Setup the URL bar buttons.
65     connect(backButtonPointer, SIGNAL(clicked()), webEngineViewPointer, SLOT(back()));
66     connect(forwardButtonPointer, SIGNAL(clicked()), webEngineViewPointer, SLOT(forward()));
67     connect(refreshButtonPointer, SIGNAL(clicked()), webEngineViewPointer, SLOT(reload()));
68     connect(homeButtonPointer, SIGNAL(clicked()), this, SLOT(goHome()));
69     connect(javaScriptButtonPointer, SIGNAL(clicked()), this, SLOT(toggleJavaScript()));
70
71     // Instantiate the mouse event pointer.
72     MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter(webEngineViewPointer);
73
74     // Install the mouse event filter.
75     qApp->installEventFilter(mouseEventFilterPointer);
76
77     // Listen for hovered link URLs.
78     connect(webEnginePagePointer, SIGNAL(linkHovered(const QString)), this, SLOT(pageLinkHovered(const QString)));
79
80     // Instantiate the URL request interceptor.
81     UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
82
83     // Set the URL request interceptor.
84     webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
85
86     // Reapply the domain settings when the host changes.
87     connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings()), this, SLOT(applyDomainSettingsWithoutReloading()));
88
89     // Disable the cache.
90     webEngineProfilePointer->setHttpCacheType(QWebEngineProfile::NoCache);
91
92     // Don't allow JavaScript to open windows.
93     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
94
95     // Set the zoom factor.
96     webEngineViewPointer->setZoomFactor(Settings::zoomFactor());
97
98     // Apply the application settings.
99     applyApplicationSettings();
100
101     // Apply the domain settings.  `false` does not reload the website.
102     applyDomainSettings(false);
103
104     // Set the focus on the WebEngine view.
105     webEngineViewPointer->setFocus();
106
107     // Get the arguments.
108     QStringList argumentsStringList = qApp->arguments();
109
110     // Check to see if the arguments lists contains a URL.
111     if (argumentsStringList.size() > 1)
112     {
113         // Load the URL from the arguments list.
114         webEngineViewPointer->setUrl(QUrl::fromUserInput(argumentsStringList.at(1)));
115     }
116     else
117     {
118         // Load the homepage.
119         goHome();
120     }
121 }
122
123 void MainView::applyApplicationSettings() const
124 {
125     // TODO.
126 }
127
128 // This exists as a separate function from `applyDomainSettings()` so it can be listed as a slot and function without the need for a boolean argument.
129 void MainView::applyDomainSettingsAndReload() const
130 {
131     // Apply the domain settings.  `true` reloads the website.
132     applyDomainSettings(true);
133 }
134
135 // This exists as a separate function from `applyDomainSettings()` so it can be listed as a slot and function without the need for a boolean argument.
136 void MainView::applyDomainSettingsWithoutReloading() const
137 {
138     // Apply the domain settings  `false` does not reload the website.
139     applyDomainSettings(false);
140 }
141
142 void MainView::applyDomainSettings(bool reloadWebsite) const
143 {
144     // Set the JavaScript status.
145     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScript());
146
147     // Update the JavaScript button.
148     if (Settings::javaScript())
149     {
150         javaScriptButtonPointer->setIcon(QIcon(":/icons/javascript-warning"));
151     }
152     else
153     {
154         javaScriptButtonPointer->setIcon(QIcon(":/icons/privacy-mode"));
155     }
156
157     // Apply the user agent.
158     webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgent(Settings::userAgent()));
159
160     // Reload the website if requested.
161     if (reloadWebsite)
162     {
163         webEngineViewPointer->reload();
164     }
165 }
166
167 void MainView::goHome() const
168 {
169     // Load the homepage.
170     webEngineViewPointer->setUrl(QUrl::fromUserInput(Settings::homepage()));
171 }
172
173 void MainView::loadUrlFromTextBox(QString urlFromUser) const
174 {
175     // Remove the focus from the URL line edit.
176     urlLineEditPointer->clearFocus();
177
178     // Decide if the text is more likely to be a URL or a search.
179     if (urlFromUser.contains("."))  // The text is likely a URL.
180     {
181         // Check if the URL does not start with a valid protocol.
182         if (!urlFromUser.startsWith("http") && !urlFromUser.startsWith("file://"))
183         {
184             // Add `https://` to the beginning of the URL.
185             urlFromUser = "https://" + urlFromUser;
186         }
187
188         // Load the URL.
189         webEngineViewPointer->setUrl(QUrl::fromUserInput(urlFromUser));
190     }
191     else  // The text is likely a search.
192     {
193         // Load the search.
194         webEngineViewPointer->setUrl(QUrl::fromUserInput(SearchEngineHelper::getSearchUrl(Settings::searchEngine()) + urlFromUser));
195     }
196 }
197
198 void MainView::pageLinkHovered(const QString &linkUrl) const
199 {
200     // Emit a signal so that the browser window can update the status bar.
201     emit linkHovered(linkUrl);
202 }
203
204 void MainView::toggleJavaScript() const
205 {
206     // Toggle JavaScript.
207     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
208
209     // Update the JavaScript button.
210     if (webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled))
211     {
212         javaScriptButtonPointer->setIcon(QIcon(":/icons/javascript-warning"));
213     }
214     else
215     {
216         javaScriptButtonPointer->setIcon(QIcon(":/icons/privacy-mode"));
217     }
218
219     // Reload the website.
220     webEngineViewPointer->reload();
221 }
222
223 void MainView::updateInterface() const
224 {
225     // Update the URL line edit if it does not have focus.
226     if (!urlLineEditPointer->hasFocus())
227     {
228         // Update the URL line edit.
229         urlLineEditPointer->setText(webEngineViewPointer->url().toString());
230     }
231
232     // Update the status of the forward and back buttons.
233     backButtonPointer->setEnabled(webEngineHistoryPointer->canGoBack());
234     forwardButtonPointer->setEnabled(webEngineHistoryPointer->canGoForward());
235
236     // Reapply the zoom factor.  This is a bug in QWebEngineView that resets the zoom with every load.  Hopefully it will be fixed in Qt6.  <https://bugreports.qt.io/browse/QTBUG-51992>
237     webEngineViewPointer->setZoomFactor(Settings::zoomFactor());
238 }