main, applets/web: Re-add progress dialog for RomFS extraction

This commit is contained in:
Morph 2020-11-30 10:15:00 -05:00
parent 93cb783853
commit 8b95bf041d
8 changed files with 126 additions and 69 deletions

View file

@ -12,11 +12,12 @@ WebBrowserApplet::~WebBrowserApplet() = default;
DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default;
void DefaultWebBrowserApplet::OpenLocalWebPage( void DefaultWebBrowserApplet::OpenLocalWebPage(
std::string_view local_url, std::function<void(WebExitReason, std::string)> callback) const { std::string_view local_url, std::function<void()> extract_romfs_callback,
std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}",
local_url); local_url);
callback(WebExitReason::WindowClosed, "http://localhost/"); callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
} }
} // namespace Core::Frontend } // namespace Core::Frontend

View file

@ -9,8 +9,6 @@
#include "core/hle/service/am/applets/web_types.h" #include "core/hle/service/am/applets/web_types.h"
using namespace Service::AM::Applets;
namespace Core::Frontend { namespace Core::Frontend {
class WebBrowserApplet { class WebBrowserApplet {
@ -18,16 +16,17 @@ public:
virtual ~WebBrowserApplet(); virtual ~WebBrowserApplet();
virtual void OpenLocalWebPage( virtual void OpenLocalWebPage(
std::string_view local_url, std::string_view local_url, std::function<void()> extract_romfs_callback,
std::function<void(WebExitReason, std::string)> callback) const = 0; std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
}; };
class DefaultWebBrowserApplet final : public WebBrowserApplet { class DefaultWebBrowserApplet final : public WebBrowserApplet {
public: public:
~DefaultWebBrowserApplet() override; ~DefaultWebBrowserApplet() override;
void OpenLocalWebPage(std::string_view local_url, void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
std::function<void(WebExitReason, std::string)> callback) const override; std::function<void(Service::AM::Applets::WebExitReason, std::string)>
callback) const override;
}; };
} // namespace Core::Frontend } // namespace Core::Frontend

View file

@ -15,7 +15,6 @@
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h" #include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/system_archive.h" #include "core/file_sys/system_archive/system_archive.h"
#include "core/file_sys/vfs_types.h"
#include "core/file_sys/vfs_vector.h" #include "core/file_sys/vfs_vector.h"
#include "core/frontend/applets/web_browser.h" #include "core/frontend/applets/web_browser.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -311,6 +310,18 @@ void WebBrowser::Execute() {
} }
} }
void WebBrowser::ExtractOfflineRomFS() {
LOG_DEBUG(Service_AM, "Extracting RomFS to {}", offline_cache_dir);
const auto extracted_romfs_dir =
FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
const auto temp_dir =
system.GetFilesystem()->CreateDirectory(offline_cache_dir, FileSys::Mode::ReadWrite);
FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir);
}
void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) { void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) {
if ((web_arg_header.shim_kind == ShimKind::Share && if ((web_arg_header.shim_kind == ShimKind::Share &&
web_applet_version >= WebAppletVersion::Version196608) || web_applet_version >= WebAppletVersion::Version196608) ||
@ -360,12 +371,11 @@ void WebBrowser::InitializeOffline() {
const auto document_kind = const auto document_kind =
ParseRawValue<DocumentKind>(GetInputTLVData(WebArgInputTLVType::DocumentKind).value()); ParseRawValue<DocumentKind>(GetInputTLVData(WebArgInputTLVType::DocumentKind).value());
u64 title_id{};
FileSys::ContentRecordType nca_type{FileSys::ContentRecordType::HtmlDocument};
std::string additional_paths; std::string additional_paths;
switch (document_kind) { switch (document_kind) {
case DocumentKind::OfflineHtmlPage: case DocumentKind::OfflineHtmlPage:
default:
title_id = system.CurrentProcess()->GetTitleID(); title_id = system.CurrentProcess()->GetTitleID();
nca_type = FileSys::ContentRecordType::HtmlDocument; nca_type = FileSys::ContentRecordType::HtmlDocument;
additional_paths = "html-document"; additional_paths = "html-document";
@ -395,31 +405,6 @@ void WebBrowser::InitializeOffline() {
offline_document = Common::FS::SanitizePath( offline_document = Common::FS::SanitizePath(
fmt::format("{}/{}/{}", offline_cache_dir, additional_paths, document_path), fmt::format("{}/{}/{}", offline_cache_dir, additional_paths, document_path),
Common::FS::DirectorySeparator::PlatformDefault); Common::FS::DirectorySeparator::PlatformDefault);
const auto main_url = Common::FS::SanitizePath(GetMainURL(offline_document),
Common::FS::DirectorySeparator::PlatformDefault);
if (Common::FS::Exists(main_url)) {
return;
}
auto offline_romfs = GetOfflineRomFS(system, title_id, nca_type);
if (offline_romfs == nullptr) {
LOG_ERROR(Service_AM, "RomFS with title_id={:016X} and nca_type={} cannot be extracted!",
title_id, nca_type);
return;
}
LOG_DEBUG(Service_AM, "Extracting RomFS to {}", offline_cache_dir);
const auto extracted_romfs_dir =
FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
const auto temp_dir =
system.GetFilesystem()->CreateDirectory(offline_cache_dir, FileSys::Mode::ReadWrite);
FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir);
} }
void WebBrowser::InitializeShare() {} void WebBrowser::InitializeShare() {}
@ -441,11 +426,28 @@ void WebBrowser::ExecuteLogin() {
} }
void WebBrowser::ExecuteOffline() { void WebBrowser::ExecuteOffline() {
const auto main_url = Common::FS::SanitizePath(GetMainURL(offline_document),
Common::FS::DirectorySeparator::PlatformDefault);
if (!Common::FS::Exists(main_url)) {
offline_romfs = GetOfflineRomFS(system, title_id, nca_type);
if (offline_romfs == nullptr) {
LOG_ERROR(Service_AM,
"RomFS with title_id={:016X} and nca_type={} cannot be extracted!", title_id,
nca_type);
WebBrowserExit(WebExitReason::WindowClosed);
return;
}
}
LOG_INFO(Service_AM, "Opening offline document at {}", offline_document); LOG_INFO(Service_AM, "Opening offline document at {}", offline_document);
frontend.OpenLocalWebPage(offline_document,
[this](WebExitReason exit_reason, std::string last_url) { frontend.OpenLocalWebPage(
WebBrowserExit(exit_reason, last_url); offline_document, [this] { ExtractOfflineRomFS(); },
}); [this](WebExitReason exit_reason, std::string last_url) {
WebBrowserExit(exit_reason, last_url);
});
} }
void WebBrowser::ExecuteShare() { void WebBrowser::ExecuteShare() {

View file

@ -8,6 +8,7 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/am/applets/applets.h" #include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/web_types.h" #include "core/hle/service/am/applets/web_types.h"
@ -16,6 +17,10 @@ namespace Core {
class System; class System;
} }
namespace FileSys {
enum class ContentRecordType : u8;
}
namespace Service::AM::Applets { namespace Service::AM::Applets {
class WebBrowser final : public Applet { class WebBrowser final : public Applet {
@ -31,6 +36,8 @@ public:
void ExecuteInteractive() override; void ExecuteInteractive() override;
void Execute() override; void Execute() override;
void ExtractOfflineRomFS();
void WebBrowserExit(WebExitReason exit_reason, std::string last_url = ""); void WebBrowserExit(WebExitReason exit_reason, std::string last_url = "");
private: private:
@ -66,8 +73,11 @@ private:
WebArgHeader web_arg_header; WebArgHeader web_arg_header;
WebArgInputTLVMap web_arg_input_tlv_map; WebArgInputTLVMap web_arg_input_tlv_map;
u64 title_id;
FileSys::ContentRecordType nca_type;
std::string offline_cache_dir; std::string offline_cache_dir;
std::string offline_document; std::string offline_document;
FileSys::VirtualFile offline_romfs;
Core::System& system; Core::System& system;
}; };

View file

@ -120,7 +120,7 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system)
[this] { [this] {
if (page()->url() == url_interceptor->GetRequestedURL()) { if (page()->url() == url_interceptor->GetRequestedURL()) {
SetFinished(true); SetFinished(true);
SetExitReason(WebExitReason::WindowClosed); SetExitReason(Service::AM::Applets::WebExitReason::WindowClosed);
} }
}, },
Qt::QueuedConnection); Qt::QueuedConnection);
@ -135,7 +135,7 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
std::string_view additional_args) { std::string_view additional_args) {
SetUserAgent(UserAgent::WebApplet); SetUserAgent(UserAgent::WebApplet);
SetFinished(false); SetFinished(false);
SetExitReason(WebExitReason::EndButtonPressed); SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed);
SetLastURL("http://localhost/"); SetLastURL("http://localhost/");
StartInputThread(); StartInputThread();
@ -176,11 +176,11 @@ void QtNXWebEngineView::SetFinished(bool finished_) {
finished = finished_; finished = finished_;
} }
WebExitReason QtNXWebEngineView::GetExitReason() const { Service::AM::Applets::WebExitReason QtNXWebEngineView::GetExitReason() const {
return exit_reason; return exit_reason;
} }
void QtNXWebEngineView::SetExitReason(WebExitReason exit_reason_) { void QtNXWebEngineView::SetExitReason(Service::AM::Applets::WebExitReason exit_reason_) {
exit_reason = exit_reason_; exit_reason = exit_reason_;
} }
@ -316,6 +316,8 @@ void QtNXWebEngineView::InputThread() {
QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
connect(this, &QtWebBrowser::MainWindowOpenLocalWebPage, &main_window, connect(this, &QtWebBrowser::MainWindowOpenLocalWebPage, &main_window,
&GMainWindow::WebBrowserOpenLocalWebPage, Qt::QueuedConnection); &GMainWindow::WebBrowserOpenLocalWebPage, Qt::QueuedConnection);
connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
&QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
connect(&main_window, &GMainWindow::WebBrowserClosed, this, connect(&main_window, &GMainWindow::WebBrowserClosed, this,
&QtWebBrowser::MainWindowWebBrowserClosed, Qt::QueuedConnection); &QtWebBrowser::MainWindowWebBrowserClosed, Qt::QueuedConnection);
} }
@ -323,7 +325,9 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
QtWebBrowser::~QtWebBrowser() = default; QtWebBrowser::~QtWebBrowser() = default;
void QtWebBrowser::OpenLocalWebPage( void QtWebBrowser::OpenLocalWebPage(
std::string_view local_url, std::function<void(WebExitReason, std::string)> callback) const { std::string_view local_url, std::function<void()> extract_romfs_callback,
std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
this->extract_romfs_callback = std::move(extract_romfs_callback);
this->callback = std::move(callback); this->callback = std::move(callback);
const auto index = local_url.find('?'); const auto index = local_url.find('?');
@ -335,6 +339,11 @@ void QtWebBrowser::OpenLocalWebPage(
} }
} }
void QtWebBrowser::MainWindowWebBrowserClosed(WebExitReason exit_reason, std::string last_url) { void QtWebBrowser::MainWindowExtractOfflineRomFS() {
extract_romfs_callback();
}
void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason,
std::string last_url) {
callback(exit_reason, last_url); callback(exit_reason, last_url);
} }

View file

@ -69,8 +69,8 @@ public:
[[nodiscard]] bool IsFinished() const; [[nodiscard]] bool IsFinished() const;
void SetFinished(bool finished_); void SetFinished(bool finished_);
[[nodiscard]] WebExitReason GetExitReason() const; [[nodiscard]] Service::AM::Applets::WebExitReason GetExitReason() const;
void SetExitReason(WebExitReason exit_reason_); void SetExitReason(Service::AM::Applets::WebExitReason exit_reason_);
[[nodiscard]] const std::string& GetLastURL() const; [[nodiscard]] const std::string& GetLastURL() const;
void SetLastURL(std::string last_url_); void SetLastURL(std::string last_url_);
@ -148,7 +148,8 @@ private:
std::atomic<bool> finished{}; std::atomic<bool> finished{};
WebExitReason exit_reason{WebExitReason::EndButtonPressed}; Service::AM::Applets::WebExitReason exit_reason{
Service::AM::Applets::WebExitReason::EndButtonPressed};
std::string last_url{"http://localhost/"}; std::string last_url{"http://localhost/"};
}; };
@ -162,15 +163,21 @@ public:
explicit QtWebBrowser(GMainWindow& parent); explicit QtWebBrowser(GMainWindow& parent);
~QtWebBrowser() override; ~QtWebBrowser() override;
void OpenLocalWebPage(std::string_view local_url, void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
std::function<void(WebExitReason, std::string)> callback) const override; std::function<void(Service::AM::Applets::WebExitReason, std::string)>
callback) const override;
signals: signals:
void MainWindowOpenLocalWebPage(std::string_view main_url, void MainWindowOpenLocalWebPage(std::string_view main_url,
std::string_view additional_args) const; std::string_view additional_args) const;
private: private:
void MainWindowWebBrowserClosed(WebExitReason exit_reason, std::string last_url); void MainWindowExtractOfflineRomFS();
mutable std::function<void(WebExitReason, std::string)> callback; void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason,
std::string last_url);
mutable std::function<void()> extract_romfs_callback;
mutable std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback;
}; };

View file

@ -372,25 +372,50 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
QtNXWebEngineView web_browser_view(this, Core::System::GetInstance()); QtNXWebEngineView web_browser_view(this, Core::System::GetInstance());
web_browser_view.LoadLocalWebPage(main_url, additional_args);
ui.action_Pause->setEnabled(false); ui.action_Pause->setEnabled(false);
ui.action_Restart->setEnabled(false); ui.action_Restart->setEnabled(false);
ui.action_Stop->setEnabled(false); ui.action_Stop->setEnabled(false);
if (render_window->IsLoadingComplete()) { {
render_window->hide(); QProgressDialog loading_progress(this);
loading_progress.setLabelText(tr("Loading Web Applet..."));
loading_progress.setRange(0, 3);
loading_progress.setValue(0);
if (!Common::FS::Exists(std::string(main_url))) {
loading_progress.show();
auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); });
while (!future.isFinished()) {
QCoreApplication::processEvents();
}
}
loading_progress.setValue(1);
web_browser_view.LoadLocalWebPage(main_url, additional_args);
if (render_window->IsLoadingComplete()) {
render_window->hide();
}
const auto& layout = render_window->GetFramebufferLayout();
web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight());
web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height());
web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth()) /
static_cast<qreal>(Layout::ScreenUndocked::Width));
web_browser_view.setFocus();
web_browser_view.show();
loading_progress.setValue(2);
QCoreApplication::processEvents();
loading_progress.setValue(3);
} }
const auto& layout = render_window->GetFramebufferLayout();
web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight());
web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height());
web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth()) /
static_cast<qreal>(Layout::ScreenUndocked::Width));
web_browser_view.setFocus();
web_browser_view.show();
bool exit_check = false; bool exit_check = false;
while (!web_browser_view.IsFinished()) { while (!web_browser_view.IsFinished()) {
@ -402,7 +427,8 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
exit_check = false; exit_check = false;
if (variant.toBool()) { if (variant.toBool()) {
web_browser_view.SetFinished(true); web_browser_view.SetFinished(true);
web_browser_view.SetExitReason(WebExitReason::EndButtonPressed); web_browser_view.SetExitReason(
Service::AM::Applets::WebExitReason::EndButtonPressed);
} }
}); });
@ -412,7 +438,7 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
if (web_browser_view.GetCurrentURL().contains(QStringLiteral("localhost"))) { if (web_browser_view.GetCurrentURL().contains(QStringLiteral("localhost"))) {
if (!web_browser_view.IsFinished()) { if (!web_browser_view.IsFinished()) {
web_browser_view.SetFinished(true); web_browser_view.SetFinished(true);
web_browser_view.SetExitReason(WebExitReason::CallbackURL); web_browser_view.SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL);
} }
web_browser_view.SetLastURL(web_browser_view.GetCurrentURL().toStdString()); web_browser_view.SetLastURL(web_browser_view.GetCurrentURL().toStdString());
@ -436,12 +462,14 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
ui.action_Restart->setEnabled(true); ui.action_Restart->setEnabled(true);
ui.action_Stop->setEnabled(true); ui.action_Stop->setEnabled(true);
QCoreApplication::processEvents();
emit WebBrowserClosed(exit_reason, last_url); emit WebBrowserClosed(exit_reason, last_url);
#else #else
// Utilize the same fallback as the default web browser applet. // Utilize the same fallback as the default web browser applet.
emit WebBrowserClosed(WebExitReason::WindowClosed, "http://localhost"); emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost");
#endif #endif
} }

View file

@ -130,6 +130,7 @@ signals:
void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
void SoftwareKeyboardFinishedCheckDialog(); void SoftwareKeyboardFinishedCheckDialog();
void WebBrowserExtractOfflineRomFS();
void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
public slots: public slots: