summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/frontend/applets/web_browser.cpp9
-rw-r--r--src/core/frontend/applets/web_browser.h8
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp12
-rw-r--r--src/core/hle/service/am/applets/web_browser.h2
-rw-r--r--src/yuzu/applets/web_browser.cpp148
-rw-r--r--src/yuzu/applets/web_browser.h33
-rw-r--r--src/yuzu/main.cpp16
-rw-r--r--src/yuzu/main.h3
8 files changed, 167 insertions, 64 deletions
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp
index a5d8f82ac..50db6a654 100644
--- a/src/core/frontend/applets/web_browser.cpp
+++ b/src/core/frontend/applets/web_browser.cpp
@@ -20,4 +20,13 @@ void DefaultWebBrowserApplet::OpenLocalWebPage(
20 callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); 20 callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
21} 21}
22 22
23void DefaultWebBrowserApplet::OpenExternalWebPage(
24 std::string_view external_url,
25 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
26 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
27 external_url);
28
29 callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
30}
31
23} // namespace Core::Frontend 32} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index 5b0629cfb..1c5ef19a9 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -18,6 +18,10 @@ public:
18 virtual void OpenLocalWebPage( 18 virtual void OpenLocalWebPage(
19 std::string_view local_url, std::function<void()> extract_romfs_callback, 19 std::string_view local_url, std::function<void()> extract_romfs_callback,
20 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; 20 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
21
22 virtual void OpenExternalWebPage(
23 std::string_view external_url,
24 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
21}; 25};
22 26
23class DefaultWebBrowserApplet final : public WebBrowserApplet { 27class DefaultWebBrowserApplet final : public WebBrowserApplet {
@@ -27,6 +31,10 @@ public:
27 void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback, 31 void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
28 std::function<void(Service::AM::Applets::WebExitReason, std::string)> 32 std::function<void(Service::AM::Applets::WebExitReason, std::string)>
29 callback) const override; 33 callback) const override;
34
35 void OpenExternalWebPage(std::string_view external_url,
36 std::function<void(Service::AM::Applets::WebExitReason, std::string)>
37 callback) const override;
30}; 38};
31 39
32} // namespace Core::Frontend 40} // namespace Core::Frontend
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 9c8be156f..2ab420789 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -409,7 +409,9 @@ void WebBrowser::InitializeOffline() {
409 409
410void WebBrowser::InitializeShare() {} 410void WebBrowser::InitializeShare() {}
411 411
412void WebBrowser::InitializeWeb() {} 412void WebBrowser::InitializeWeb() {
413 external_url = ParseStringValue(GetInputTLVData(WebArgInputTLVType::InitialURL).value());
414}
413 415
414void WebBrowser::InitializeWifi() {} 416void WebBrowser::InitializeWifi() {}
415 417
@@ -456,8 +458,12 @@ void WebBrowser::ExecuteShare() {
456} 458}
457 459
458void WebBrowser::ExecuteWeb() { 460void WebBrowser::ExecuteWeb() {
459 LOG_WARNING(Service_AM, "(STUBBED) called, Web Applet is not implemented"); 461 LOG_INFO(Service_AM, "Opening external URL at {}", external_url);
460 WebBrowserExit(WebExitReason::EndButtonPressed); 462
463 frontend.OpenExternalWebPage(external_url,
464 [this](WebExitReason exit_reason, std::string last_url) {
465 WebBrowserExit(exit_reason, last_url);
466 });
461} 467}
462 468
463void WebBrowser::ExecuteWifi() { 469void WebBrowser::ExecuteWifi() {
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 936a49a86..04c274754 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -79,6 +79,8 @@ private:
79 std::string offline_document; 79 std::string offline_document;
80 FileSys::VirtualFile offline_romfs; 80 FileSys::VirtualFile offline_romfs;
81 81
82 std::string external_url;
83
82 Core::System& system; 84 Core::System& system;
83}; 85};
84 86
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp
index 7e2dc6ee9..e482ba029 100644
--- a/src/yuzu/applets/web_browser.cpp
+++ b/src/yuzu/applets/web_browser.cpp
@@ -51,59 +51,32 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
51 InputCommon::InputSubsystem* input_subsystem_) 51 InputCommon::InputSubsystem* input_subsystem_)
52 : QWebEngineView(parent), input_subsystem{input_subsystem_}, 52 : QWebEngineView(parent), input_subsystem{input_subsystem_},
53 url_interceptor(std::make_unique<UrlRequestInterceptor>()), 53 url_interceptor(std::make_unique<UrlRequestInterceptor>()),
54 input_interpreter(std::make_unique<InputInterpreter>(system)) { 54 input_interpreter(std::make_unique<InputInterpreter>(system)),
55 QWebEngineScript nx_font_css; 55 default_profile{QWebEngineProfile::defaultProfile()},
56 QWebEngineScript load_nx_font; 56 global_settings{QWebEngineSettings::globalSettings()} {
57 QWebEngineScript gamepad; 57 QWebEngineScript gamepad;
58 QWebEngineScript window_nx; 58 QWebEngineScript window_nx;
59 59
60 const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath(
61 fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))));
62
63 nx_font_css.setName(QStringLiteral("nx_font_css.js"));
64 load_nx_font.setName(QStringLiteral("load_nx_font.js"));
65 gamepad.setName(QStringLiteral("gamepad_script.js")); 60 gamepad.setName(QStringLiteral("gamepad_script.js"));
66 window_nx.setName(QStringLiteral("window_nx_script.js")); 61 window_nx.setName(QStringLiteral("window_nx_script.js"));
67 62
68 nx_font_css.setSourceCode(
69 QString::fromStdString(NX_FONT_CSS)
70 .arg(fonts_dir + QStringLiteral("/FontStandard.ttf"))
71 .arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf"))
72 .arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf"))
73 .arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf"))
74 .arg(fonts_dir + QStringLiteral("/FontKorean.ttf"))
75 .arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf"))
76 .arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf")));
77 load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT));
78 gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT)); 63 gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT));
79 window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT)); 64 window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT));
80 65
81 nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady);
82 load_nx_font.setInjectionPoint(QWebEngineScript::Deferred);
83 gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation); 66 gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation);
84 window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation); 67 window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation);
85 68
86 nx_font_css.setWorldId(QWebEngineScript::MainWorld);
87 load_nx_font.setWorldId(QWebEngineScript::MainWorld);
88 gamepad.setWorldId(QWebEngineScript::MainWorld); 69 gamepad.setWorldId(QWebEngineScript::MainWorld);
89 window_nx.setWorldId(QWebEngineScript::MainWorld); 70 window_nx.setWorldId(QWebEngineScript::MainWorld);
90 71
91 nx_font_css.setRunsOnSubFrames(true);
92 load_nx_font.setRunsOnSubFrames(true);
93 gamepad.setRunsOnSubFrames(true); 72 gamepad.setRunsOnSubFrames(true);
94 window_nx.setRunsOnSubFrames(true); 73 window_nx.setRunsOnSubFrames(true);
95 74
96 auto* default_profile = QWebEngineProfile::defaultProfile();
97
98 default_profile->scripts()->insert(nx_font_css);
99 default_profile->scripts()->insert(load_nx_font);
100 default_profile->scripts()->insert(gamepad); 75 default_profile->scripts()->insert(gamepad);
101 default_profile->scripts()->insert(window_nx); 76 default_profile->scripts()->insert(window_nx);
102 77
103 default_profile->setRequestInterceptor(url_interceptor.get()); 78 default_profile->setRequestInterceptor(url_interceptor.get());
104 79
105 auto* global_settings = QWebEngineSettings::globalSettings();
106
107 global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); 80 global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
108 global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); 81 global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
109 global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); 82 global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true);
@@ -111,13 +84,7 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
111 global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true); 84 global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true);
112 global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false); 85 global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false);
113 86
114 connect( 87 global_settings->setFontFamily(QWebEngineSettings::StandardFont, QStringLiteral("Roboto"));
115 url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(),
116 [this] {
117 std::this_thread::sleep_for(std::chrono::milliseconds(50));
118 page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT));
119 },
120 Qt::QueuedConnection);
121 88
122 connect( 89 connect(
123 page(), &QWebEnginePage::windowCloseRequested, page(), 90 page(), &QWebEnginePage::windowCloseRequested, page(),
@@ -137,6 +104,9 @@ QtNXWebEngineView::~QtNXWebEngineView() {
137 104
138void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, 105void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
139 std::string_view additional_args) { 106 std::string_view additional_args) {
107 is_local = true;
108
109 LoadExtractedFonts();
140 SetUserAgent(UserAgent::WebApplet); 110 SetUserAgent(UserAgent::WebApplet);
141 SetFinished(false); 111 SetFinished(false);
142 SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); 112 SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed);
@@ -147,6 +117,20 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
147 QString::fromStdString(std::string(additional_args)))); 117 QString::fromStdString(std::string(additional_args))));
148} 118}
149 119
120void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url,
121 std::string_view additional_args) {
122 is_local = false;
123
124 SetUserAgent(UserAgent::WebApplet);
125 SetFinished(false);
126 SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed);
127 SetLastURL("http://localhost/");
128 StartInputThread();
129
130 load(QUrl(QString::fromStdString(std::string(main_url)) +
131 QString::fromStdString(std::string(additional_args))));
132}
133
150void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { 134void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) {
151 const QString user_agent_str = [user_agent] { 135 const QString user_agent_str = [user_agent] {
152 switch (user_agent) { 136 switch (user_agent) {
@@ -208,11 +192,15 @@ void QtNXWebEngineView::hide() {
208} 192}
209 193
210void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) { 194void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) {
211 input_subsystem->GetKeyboard()->PressKey(event->key()); 195 if (is_local) {
196 input_subsystem->GetKeyboard()->PressKey(event->key());
197 }
212} 198}
213 199
214void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) { 200void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) {
215 input_subsystem->GetKeyboard()->ReleaseKey(event->key()); 201 if (is_local) {
202 input_subsystem->GetKeyboard()->ReleaseKey(event->key());
203 }
216} 204}
217 205
218template <HIDButton... T> 206template <HIDButton... T>
@@ -294,7 +282,10 @@ void QtNXWebEngineView::StartInputThread() {
294} 282}
295 283
296void QtNXWebEngineView::StopInputThread() { 284void QtNXWebEngineView::StopInputThread() {
297 QWidget::releaseKeyboard(); 285 if (is_local) {
286 QWidget::releaseKeyboard();
287 }
288
298 input_thread_running = false; 289 input_thread_running = false;
299 if (input_thread.joinable()) { 290 if (input_thread.joinable()) {
300 input_thread.join(); 291 input_thread.join();
@@ -305,7 +296,9 @@ void QtNXWebEngineView::InputThread() {
305 // Wait for 1 second before allowing any inputs to be processed. 296 // Wait for 1 second before allowing any inputs to be processed.
306 std::this_thread::sleep_for(std::chrono::seconds(1)); 297 std::this_thread::sleep_for(std::chrono::seconds(1));
307 298
308 QWidget::grabKeyboard(); 299 if (is_local) {
300 QWidget::grabKeyboard();
301 }
309 302
310 while (input_thread_running) { 303 while (input_thread_running) {
311 input_interpreter->PollInput(); 304 input_interpreter->PollInput();
@@ -326,11 +319,53 @@ void QtNXWebEngineView::InputThread() {
326 } 319 }
327} 320}
328 321
322void QtNXWebEngineView::LoadExtractedFonts() {
323 QWebEngineScript nx_font_css;
324 QWebEngineScript load_nx_font;
325
326 const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath(
327 fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))));
328
329 nx_font_css.setName(QStringLiteral("nx_font_css.js"));
330 load_nx_font.setName(QStringLiteral("load_nx_font.js"));
331
332 nx_font_css.setSourceCode(
333 QString::fromStdString(NX_FONT_CSS)
334 .arg(fonts_dir + QStringLiteral("/FontStandard.ttf"))
335 .arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf"))
336 .arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf"))
337 .arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf"))
338 .arg(fonts_dir + QStringLiteral("/FontKorean.ttf"))
339 .arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf"))
340 .arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf")));
341 load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT));
342
343 nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady);
344 load_nx_font.setInjectionPoint(QWebEngineScript::Deferred);
345
346 nx_font_css.setWorldId(QWebEngineScript::MainWorld);
347 load_nx_font.setWorldId(QWebEngineScript::MainWorld);
348
349 nx_font_css.setRunsOnSubFrames(true);
350 load_nx_font.setRunsOnSubFrames(true);
351
352 default_profile->scripts()->insert(nx_font_css);
353 default_profile->scripts()->insert(load_nx_font);
354
355 connect(
356 url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(),
357 [this] {
358 std::this_thread::sleep_for(std::chrono::milliseconds(50));
359 page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT));
360 },
361 Qt::QueuedConnection);
362}
363
329#endif 364#endif
330 365
331QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { 366QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
332 connect(this, &QtWebBrowser::MainWindowOpenLocalWebPage, &main_window, 367 connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window,
333 &GMainWindow::WebBrowserOpenLocalWebPage, Qt::QueuedConnection); 368 &GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
334 connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this, 369 connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
335 &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection); 370 &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
336 connect(&main_window, &GMainWindow::WebBrowserClosed, this, 371 connect(&main_window, &GMainWindow::WebBrowserClosed, this,
@@ -340,17 +375,32 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
340QtWebBrowser::~QtWebBrowser() = default; 375QtWebBrowser::~QtWebBrowser() = default;
341 376
342void QtWebBrowser::OpenLocalWebPage( 377void QtWebBrowser::OpenLocalWebPage(
343 std::string_view local_url, std::function<void()> extract_romfs_callback, 378 std::string_view local_url, std::function<void()> extract_romfs_callback_,
344 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { 379 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
345 this->extract_romfs_callback = std::move(extract_romfs_callback); 380 extract_romfs_callback = std::move(extract_romfs_callback_);
346 this->callback = std::move(callback); 381 callback = std::move(callback_);
347 382
348 const auto index = local_url.find('?'); 383 const auto index = local_url.find('?');
349 384
350 if (index == std::string::npos) { 385 if (index == std::string::npos) {
351 emit MainWindowOpenLocalWebPage(local_url, ""); 386 emit MainWindowOpenWebPage(local_url, "", true);
387 } else {
388 emit MainWindowOpenWebPage(local_url.substr(0, index), local_url.substr(index), true);
389 }
390}
391
392void QtWebBrowser::OpenExternalWebPage(
393 std::string_view external_url,
394 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
395 callback = std::move(callback_);
396
397 const auto index = external_url.find('?');
398
399 if (index == std::string::npos) {
400 emit MainWindowOpenWebPage(external_url, "", false);
352 } else { 401 } else {
353 emit MainWindowOpenLocalWebPage(local_url.substr(0, index), local_url.substr(index)); 402 emit MainWindowOpenWebPage(external_url.substr(0, index), external_url.substr(index),
403 false);
354 } 404 }
355} 405}
356 406
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h
index cfddaa6f8..47f960d69 100644
--- a/src/yuzu/applets/web_browser.h
+++ b/src/yuzu/applets/web_browser.h
@@ -18,8 +18,8 @@
18 18
19enum class HIDButton : u8; 19enum class HIDButton : u8;
20 20
21class InputInterpreter;
22class GMainWindow; 21class GMainWindow;
22class InputInterpreter;
23class UrlRequestInterceptor; 23class UrlRequestInterceptor;
24 24
25namespace Core { 25namespace Core {
@@ -41,6 +41,9 @@ enum class UserAgent {
41 WifiWebAuthApplet, 41 WifiWebAuthApplet,
42}; 42};
43 43
44class QWebEngineProfile;
45class QWebEngineSettings;
46
44class QtNXWebEngineView : public QWebEngineView { 47class QtNXWebEngineView : public QWebEngineView {
45 Q_OBJECT 48 Q_OBJECT
46 49
@@ -58,6 +61,14 @@ public:
58 void LoadLocalWebPage(std::string_view main_url, std::string_view additional_args); 61 void LoadLocalWebPage(std::string_view main_url, std::string_view additional_args);
59 62
60 /** 63 /**
64 * Loads an external website. Cannot be used to load local urls.
65 *
66 * @param main_url The url to the website.
67 * @param additional_args Additional arguments appended to the main url.
68 */
69 void LoadExternalWebPage(std::string_view main_url, std::string_view additional_args);
70
71 /**
61 * Sets the background color of the web page. 72 * Sets the background color of the web page.
62 * 73 *
63 * @param color The color to set. 74 * @param color The color to set.
@@ -147,6 +158,9 @@ private:
147 /// The thread where input is being polled and processed. 158 /// The thread where input is being polled and processed.
148 void InputThread(); 159 void InputThread();
149 160
161 /// Loads the extracted fonts using JavaScript.
162 void LoadExtractedFonts();
163
150 InputCommon::InputSubsystem* input_subsystem; 164 InputCommon::InputSubsystem* input_subsystem;
151 165
152 std::unique_ptr<UrlRequestInterceptor> url_interceptor; 166 std::unique_ptr<UrlRequestInterceptor> url_interceptor;
@@ -163,6 +177,11 @@ private:
163 Service::AM::Applets::WebExitReason::EndButtonPressed}; 177 Service::AM::Applets::WebExitReason::EndButtonPressed};
164 178
165 std::string last_url{"http://localhost/"}; 179 std::string last_url{"http://localhost/"};
180
181 bool is_local{};
182
183 QWebEngineProfile* default_profile;
184 QWebEngineSettings* global_settings;
166}; 185};
167 186
168#endif 187#endif
@@ -174,13 +193,17 @@ public:
174 explicit QtWebBrowser(GMainWindow& parent); 193 explicit QtWebBrowser(GMainWindow& parent);
175 ~QtWebBrowser() override; 194 ~QtWebBrowser() override;
176 195
177 void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback, 196 void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback_,
178 std::function<void(Service::AM::Applets::WebExitReason, std::string)> 197 std::function<void(Service::AM::Applets::WebExitReason, std::string)>
179 callback) const override; 198 callback_) const override;
199
200 void OpenExternalWebPage(std::string_view external_url,
201 std::function<void(Service::AM::Applets::WebExitReason, std::string)>
202 callback_) const override;
180 203
181signals: 204signals:
182 void MainWindowOpenLocalWebPage(std::string_view main_url, 205 void MainWindowOpenWebPage(std::string_view main_url, std::string_view additional_args,
183 std::string_view additional_args) const; 206 bool is_local) const;
184 207
185private: 208private:
186 void MainWindowExtractOfflineRomFS(); 209 void MainWindowExtractOfflineRomFS();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f835ee9cb..620e80cdc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -366,13 +366,13 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
366 emit SoftwareKeyboardFinishedCheckDialog(); 366 emit SoftwareKeyboardFinishedCheckDialog();
367} 367}
368 368
369void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url, 369void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
370 std::string_view additional_args) { 370 bool is_local) {
371#ifdef YUZU_USE_QT_WEB_ENGINE 371#ifdef YUZU_USE_QT_WEB_ENGINE
372 372
373 if (disable_web_applet) { 373 if (disable_web_applet) {
374 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, 374 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed,
375 "http://localhost"); 375 "http://localhost/");
376 return; 376 return;
377 } 377 }
378 378
@@ -388,7 +388,7 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
388 loading_progress.setRange(0, 3); 388 loading_progress.setRange(0, 3);
389 loading_progress.setValue(0); 389 loading_progress.setValue(0);
390 390
391 if (!Common::FS::Exists(std::string(main_url))) { 391 if (is_local && !Common::FS::Exists(std::string(main_url))) {
392 loading_progress.show(); 392 loading_progress.show();
393 393
394 auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); }); 394 auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); });
@@ -400,7 +400,11 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
400 400
401 loading_progress.setValue(1); 401 loading_progress.setValue(1);
402 402
403 web_browser_view.LoadLocalWebPage(main_url, additional_args); 403 if (is_local) {
404 web_browser_view.LoadLocalWebPage(main_url, additional_args);
405 } else {
406 web_browser_view.LoadExternalWebPage(main_url, additional_args);
407 }
404 408
405 if (render_window->IsLoadingComplete()) { 409 if (render_window->IsLoadingComplete()) {
406 render_window->hide(); 410 render_window->hide();
@@ -493,7 +497,7 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
493#else 497#else
494 498
495 // Utilize the same fallback as the default web browser applet. 499 // Utilize the same fallback as the default web browser applet.
496 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost"); 500 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
497 501
498#endif 502#endif
499} 503}
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index b140995bf..22f82b20e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -142,7 +142,8 @@ public slots:
142 void ProfileSelectorSelectProfile(); 142 void ProfileSelectorSelectProfile();
143 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); 143 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
144 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); 144 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
145 void WebBrowserOpenLocalWebPage(std::string_view main_url, std::string_view additional_args); 145 void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
146 bool is_local);
146 void OnAppFocusStateChanged(Qt::ApplicationState state); 147 void OnAppFocusStateChanged(Qt::ApplicationState state);
147 148
148private: 149private: