Add user agent controls.
[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
27 // Qt framework headers.
28 #include <QWebEngineProfile>
29
30 MainView::MainView(QWidget *parent) : QWidget(parent)
31 {
32     // Instantiate the mainview UI.
33     Ui::MainView mainViewUi;
34
35     // Setup the UI.
36     mainViewUi.setupUi(this);
37
38     // Get handles for the views.
39     backButtonPointer = mainViewUi.backButton;
40     forwardButtonPointer = mainViewUi.forwardButton;
41     QPushButton *homeButtonPointer = mainViewUi.homeButton;
42     urlLineEditPointer = mainViewUi.urlLineEdit;
43     javaScriptButtonPointer = mainViewUi.javaScript;
44     webEngineViewPointer = mainViewUi.webEngineView;
45
46     // Get handles for the aspects of the WebEngine.
47     QWebEnginePage *webEnginePagePointer = webEngineViewPointer->page();
48     webEngineHistoryPointer = webEnginePagePointer->history();
49     webEngineProfilePointer = webEnginePagePointer->profile();
50     webEngineSettingsPointer = webEngineViewPointer->settings();
51
52     // Update the webengine view from the URL line edit.
53     connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrl(const QString)));
54
55     // Update the URL line edit form the webengine view.
56     connect(webEngineViewPointer, SIGNAL(loadStarted()), this, SLOT(updateInterface()));
57     connect(webEngineViewPointer, SIGNAL(loadProgress(int)), this, SLOT(updateInterface()));
58     connect(webEngineViewPointer, SIGNAL(loadFinished(bool)), this, SLOT(updateInterface()));
59
60     // Setup the URL bar buttons.
61     connect(backButtonPointer, SIGNAL(clicked()), webEngineViewPointer, SLOT(back()));
62     connect(forwardButtonPointer, SIGNAL(clicked()), webEngineViewPointer, SLOT(forward()));
63     connect(homeButtonPointer, SIGNAL(clicked()), this, SLOT(goHome()));
64     connect(javaScriptButtonPointer, SIGNAL(clicked()), this, SLOT(toggleJavaScript()));
65
66     // Instantiate the mouse event pointer.
67     MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter(webEngineViewPointer);
68
69     // Install the mouse event filter.
70     qApp->installEventFilter(mouseEventFilterPointer);
71
72     // Listen for hovered link URLs.
73     connect(webEnginePagePointer, SIGNAL(linkHovered(QString)), this, SLOT(pageLinkHovered(QString)));
74
75     // Disable the cache.
76     webEngineProfilePointer->setHttpCacheType(QWebEngineProfile::NoCache);
77
78     // Instantiate the user agent helper.
79     userAgentHelperPointer = new UserAgentHelper();
80
81     // Don't allow JavaScript to open windows.
82     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
83
84     // Set the zoom factor.
85     webEngineViewPointer->setZoomFactor(Settings::zoomFactor());
86
87     // Apply the application settings.
88     applyApplicationSettings();
89
90     // Apply the domain settings.  `false` does not reload the website.
91     applyDomainSettings(false);
92
93     // Set the focus on the WebEngine view.
94     webEngineViewPointer->setFocus();
95
96     // Get the arguments.
97     QStringList argumentsStringList = qApp->arguments();
98
99     // Check to see if the arguments lists contains a URL.
100     if (argumentsStringList.size() > 1)
101     {
102         // Load the URL from the arguments list.
103         webEngineViewPointer->setUrl(QUrl::fromUserInput(argumentsStringList.at(1)));
104     }
105     else
106     {
107         // Load the homepage.
108         goHome();
109     }
110 }
111
112 void MainView::applyApplicationSettings()
113 {
114     // TODO.
115 }
116
117 void MainView::applyDomainSettingsAndReload()
118 {
119     // Apply the domain setings.  `true` reloads the website.
120     applyDomainSettings(true);
121 }
122
123 void MainView::applyDomainSettings(bool reloadWebsite)
124 {
125     // Set the JavaScript status.
126     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScript());
127
128     // Update the JavaScript button.
129     if (Settings::javaScript())
130     {
131         javaScriptButtonPointer->setIcon(QIcon(":/icons/javascript-warning"));
132     }
133     else
134     {
135         javaScriptButtonPointer->setIcon(QIcon(":/icons/privacy-mode"));
136     }
137
138     // Apply the user agent.
139     webEngineProfilePointer->setHttpUserAgent(userAgentHelperPointer->getUserAgent(Settings::userAgent()));
140
141     // Reload the website if requested.
142     if (reloadWebsite)
143     {
144         webEngineViewPointer->reload();
145     }
146 }
147
148 void MainView::goHome()
149 {
150     // Load the homepage.  TODO.  Consider sanitizing the homepage input and adding things like protocols if they are missing.
151     webEngineViewPointer->setUrl(Settings::homepage());
152 }
153
154 void MainView::loadUrl(const QString &urlFromUser)
155 {
156     // Remove the focus from the URL line edit.
157     urlLineEditPointer->clearFocus();
158
159     // Load the URL, adding standard protocol sections if needed.  TODO.  Replace this with logic that prefers HTTPS.
160     webEngineViewPointer->setUrl(QUrl::fromUserInput(urlFromUser));
161 }
162
163 void MainView::pageLinkHovered(const QString &linkUrl)
164 {
165     // Emit a signal so that the browser window can update the status bar.
166     emit linkHovered(linkUrl);
167 }
168
169 void MainView::toggleJavaScript()
170 {
171     // Toggle JavaScript.
172     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
173
174     // Update the JavaScript button.
175     if (webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled))
176     {
177         javaScriptButtonPointer->setIcon(QIcon(":/icons/javascript-warning"));
178     }
179     else
180     {
181         javaScriptButtonPointer->setIcon(QIcon(":/icons/privacy-mode"));
182     }
183
184     // Reload the website.
185     webEngineViewPointer->reload();
186 }
187
188 void MainView::updateInterface()
189 {
190     // Update the URL line edit if it does not have focus.
191     if (!urlLineEditPointer->hasFocus())
192     {
193         // Update the URL line edit.
194         urlLineEditPointer->setText(webEngineViewPointer->url().toString());
195     }
196
197     // Update the status of the forward and back buttons.
198     backButtonPointer->setEnabled(webEngineHistoryPointer->canGoBack());
199     forwardButtonPointer->setEnabled(webEngineHistoryPointer->canGoForward());
200
201     // 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>
202     webEngineViewPointer->setZoomFactor(Settings::zoomFactor());
203 }