diff options
20 files changed, 890 insertions, 129 deletions
diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp index b974f2289..c30b36de7 100644 --- a/src/core/frontend/applets/general_frontend.cpp +++ b/src/core/frontend/applets/general_frontend.cpp | |||
| @@ -7,9 +7,38 @@ | |||
| 7 | 7 | ||
| 8 | namespace Core::Frontend { | 8 | namespace Core::Frontend { |
| 9 | 9 | ||
| 10 | ParentalControlsApplet::~ParentalControlsApplet() = default; | ||
| 11 | |||
| 12 | DefaultParentalControlsApplet::~DefaultParentalControlsApplet() = default; | ||
| 13 | |||
| 14 | void DefaultParentalControlsApplet::VerifyPIN(std::function<void(bool)> finished, | ||
| 15 | bool suspend_future_verification_temporarily) { | ||
| 16 | LOG_INFO(Service_AM, | ||
| 17 | "Application requested frontend to verify PIN (normal), " | ||
| 18 | "suspend_future_verification_temporarily={}, verifying as correct.", | ||
| 19 | suspend_future_verification_temporarily); | ||
| 20 | finished(true); | ||
| 21 | } | ||
| 22 | |||
| 23 | void DefaultParentalControlsApplet::VerifyPINForSettings(std::function<void(bool)> finished) { | ||
| 24 | LOG_INFO(Service_AM, | ||
| 25 | "Application requested frontend to verify PIN (settings), verifying as correct."); | ||
| 26 | finished(true); | ||
| 27 | } | ||
| 28 | |||
| 29 | void DefaultParentalControlsApplet::RegisterPIN(std::function<void()> finished) { | ||
| 30 | LOG_INFO(Service_AM, "Application requested frontend to register new PIN"); | ||
| 31 | finished(); | ||
| 32 | } | ||
| 33 | |||
| 34 | void DefaultParentalControlsApplet::ChangePIN(std::function<void()> finished) { | ||
| 35 | LOG_INFO(Service_AM, "Application requested frontend to change PIN to new value"); | ||
| 36 | finished(); | ||
| 37 | } | ||
| 38 | |||
| 10 | PhotoViewerApplet::~PhotoViewerApplet() = default; | 39 | PhotoViewerApplet::~PhotoViewerApplet() = default; |
| 11 | 40 | ||
| 12 | DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() {} | 41 | DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() = default; |
| 13 | 42 | ||
| 14 | void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id, | 43 | void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id, |
| 15 | std::function<void()> finished) const { | 44 | std::function<void()> finished) const { |
| @@ -24,4 +53,72 @@ void DefaultPhotoViewerApplet::ShowAllPhotos(std::function<void()> finished) con | |||
| 24 | finished(); | 53 | finished(); |
| 25 | } | 54 | } |
| 26 | 55 | ||
| 56 | ECommerceApplet::~ECommerceApplet() = default; | ||
| 57 | |||
| 58 | DefaultECommerceApplet::~DefaultECommerceApplet() = default; | ||
| 59 | |||
| 60 | void DefaultECommerceApplet::ShowApplicationInformation( | ||
| 61 | std::function<void()> finished, u64 title_id, std::optional<u128> user_id, | ||
| 62 | std::optional<bool> full_display, std::optional<std::string> extra_parameter) { | ||
| 63 | const auto value = user_id.value_or(u128{}); | ||
| 64 | LOG_INFO(Service_AM, | ||
| 65 | "Application requested frontend show application information for EShop, " | ||
| 66 | "title_id={:016X}, user_id={:016X}{:016X}, full_display={}, extra_parameter={}", | ||
| 67 | title_id, value[1], value[0], | ||
| 68 | full_display.has_value() ? fmt::format("{}", *full_display) : "null", | ||
| 69 | extra_parameter.value_or("null")); | ||
| 70 | finished(); | ||
| 71 | } | ||
| 72 | |||
| 73 | void DefaultECommerceApplet::ShowAddOnContentList(std::function<void()> finished, u64 title_id, | ||
| 74 | std::optional<u128> user_id, | ||
| 75 | std::optional<bool> full_display) { | ||
| 76 | const auto value = user_id.value_or(u128{}); | ||
| 77 | LOG_INFO(Service_AM, | ||
| 78 | "Application requested frontend show add on content list for EShop, " | ||
| 79 | "title_id={:016X}, user_id={:016X}{:016X}, full_display={}", | ||
| 80 | title_id, value[1], value[0], | ||
| 81 | full_display.has_value() ? fmt::format("{}", *full_display) : "null"); | ||
| 82 | finished(); | ||
| 83 | } | ||
| 84 | |||
| 85 | void DefaultECommerceApplet::ShowSubscriptionList(std::function<void()> finished, u64 title_id, | ||
| 86 | std::optional<u128> user_id) { | ||
| 87 | const auto value = user_id.value_or(u128{}); | ||
| 88 | LOG_INFO(Service_AM, | ||
| 89 | "Application requested frontend show subscription list for EShop, title_id={:016X}, " | ||
| 90 | "user_id={:016X}{:016X}", | ||
| 91 | title_id, value[1], value[0]); | ||
| 92 | finished(); | ||
| 93 | } | ||
| 94 | |||
| 95 | void DefaultECommerceApplet::ShowConsumableItemList(std::function<void()> finished, u64 title_id, | ||
| 96 | std::optional<u128> user_id) { | ||
| 97 | const auto value = user_id.value_or(u128{}); | ||
| 98 | LOG_INFO( | ||
| 99 | Service_AM, | ||
| 100 | "Application requested frontend show consumable item list for EShop, title_id={:016X}, " | ||
| 101 | "user_id={:016X}{:016X}", | ||
| 102 | title_id, value[1], value[0]); | ||
| 103 | finished(); | ||
| 104 | } | ||
| 105 | |||
| 106 | void DefaultECommerceApplet::ShowShopHome(std::function<void()> finished, u128 user_id, | ||
| 107 | bool full_display) { | ||
| 108 | LOG_INFO(Service_AM, | ||
| 109 | "Application requested frontend show home menu for EShop, user_id={:016X}{:016X}, " | ||
| 110 | "full_display={}", | ||
| 111 | user_id[1], user_id[0], full_display); | ||
| 112 | finished(); | ||
| 113 | } | ||
| 114 | |||
| 115 | void DefaultECommerceApplet::ShowSettings(std::function<void()> finished, u128 user_id, | ||
| 116 | bool full_display) { | ||
| 117 | LOG_INFO(Service_AM, | ||
| 118 | "Application requested frontend show settings menu for EShop, user_id={:016X}{:016X}, " | ||
| 119 | "full_display={}", | ||
| 120 | user_id[1], user_id[0], full_display); | ||
| 121 | finished(); | ||
| 122 | } | ||
| 123 | |||
| 27 | } // namespace Core::Frontend | 124 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/general_frontend.h b/src/core/frontend/applets/general_frontend.h index d4506c999..4b63f828e 100644 --- a/src/core/frontend/applets/general_frontend.h +++ b/src/core/frontend/applets/general_frontend.h | |||
| @@ -5,10 +5,43 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <optional> | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | 10 | ||
| 10 | namespace Core::Frontend { | 11 | namespace Core::Frontend { |
| 11 | 12 | ||
| 13 | class ParentalControlsApplet { | ||
| 14 | public: | ||
| 15 | virtual ~ParentalControlsApplet(); | ||
| 16 | |||
| 17 | // Prompts the user to enter a PIN and calls the callback with whether or not it matches the | ||
| 18 | // correct PIN. If the bool is passed, and the PIN was recently entered correctly, the frontend | ||
| 19 | // should not prompt and simply return true. | ||
| 20 | virtual void VerifyPIN(std::function<void(bool)> finished, | ||
| 21 | bool suspend_future_verification_temporarily) = 0; | ||
| 22 | |||
| 23 | // Prompts the user to enter a PIN and calls the callback for correctness. Frontends can | ||
| 24 | // optionally alert the user that this is to change parental controls settings. | ||
| 25 | virtual void VerifyPINForSettings(std::function<void(bool)> finished) = 0; | ||
| 26 | |||
| 27 | // Prompts the user to create a new PIN for pctl and stores it with the service. | ||
| 28 | virtual void RegisterPIN(std::function<void()> finished) = 0; | ||
| 29 | |||
| 30 | // Prompts the user to verify the current PIN and then store a new one into pctl. | ||
| 31 | virtual void ChangePIN(std::function<void()> finished) = 0; | ||
| 32 | }; | ||
| 33 | |||
| 34 | class DefaultParentalControlsApplet final : public ParentalControlsApplet { | ||
| 35 | public: | ||
| 36 | ~DefaultParentalControlsApplet() override; | ||
| 37 | |||
| 38 | void VerifyPIN(std::function<void(bool)> finished, | ||
| 39 | bool suspend_future_verification_temporarily) override; | ||
| 40 | void VerifyPINForSettings(std::function<void(bool)> finished) override; | ||
| 41 | void RegisterPIN(std::function<void()> finished) override; | ||
| 42 | void ChangePIN(std::function<void()> finished) override; | ||
| 43 | }; | ||
| 44 | |||
| 12 | class PhotoViewerApplet { | 45 | class PhotoViewerApplet { |
| 13 | public: | 46 | public: |
| 14 | virtual ~PhotoViewerApplet(); | 47 | virtual ~PhotoViewerApplet(); |
| @@ -25,4 +58,55 @@ public: | |||
| 25 | void ShowAllPhotos(std::function<void()> finished) const override; | 58 | void ShowAllPhotos(std::function<void()> finished) const override; |
| 26 | }; | 59 | }; |
| 27 | 60 | ||
| 61 | class ECommerceApplet { | ||
| 62 | public: | ||
| 63 | virtual ~ECommerceApplet(); | ||
| 64 | |||
| 65 | // Shows a page with application icons, description, name, and price. | ||
| 66 | virtual void ShowApplicationInformation(std::function<void()> finished, u64 title_id, | ||
| 67 | std::optional<u128> user_id = {}, | ||
| 68 | std::optional<bool> full_display = {}, | ||
| 69 | std::optional<std::string> extra_parameter = {}) = 0; | ||
| 70 | |||
| 71 | // Shows a page with all of the add on content available for a game, with name, description, and | ||
| 72 | // price. | ||
| 73 | virtual void ShowAddOnContentList(std::function<void()> finished, u64 title_id, | ||
| 74 | std::optional<u128> user_id = {}, | ||
| 75 | std::optional<bool> full_display = {}) = 0; | ||
| 76 | |||
| 77 | // Shows a page with all of the subscriptions (recurring payments) for a game, with name, | ||
| 78 | // description, price, and renewal period. | ||
| 79 | virtual void ShowSubscriptionList(std::function<void()> finished, u64 title_id, | ||
| 80 | std::optional<u128> user_id = {}) = 0; | ||
| 81 | |||
| 82 | // Shows a page with a list of any additional game related purchasable items (DLC, | ||
| 83 | // subscriptions, etc) for a particular game, with name, description, type, and price. | ||
| 84 | virtual void ShowConsumableItemList(std::function<void()> finished, u64 title_id, | ||
| 85 | std::optional<u128> user_id = {}) = 0; | ||
| 86 | |||
| 87 | // Shows the home page of the shop. | ||
| 88 | virtual void ShowShopHome(std::function<void()> finished, u128 user_id, bool full_display) = 0; | ||
| 89 | |||
| 90 | // Shows the user settings page of the shop. | ||
| 91 | virtual void ShowSettings(std::function<void()> finished, u128 user_id, bool full_display) = 0; | ||
| 92 | }; | ||
| 93 | |||
| 94 | class DefaultECommerceApplet : public ECommerceApplet { | ||
| 95 | public: | ||
| 96 | ~DefaultECommerceApplet() override; | ||
| 97 | |||
| 98 | void ShowApplicationInformation(std::function<void()> finished, u64 title_id, | ||
| 99 | std::optional<u128> user_id, std::optional<bool> full_display, | ||
| 100 | std::optional<std::string> extra_parameter) override; | ||
| 101 | void ShowAddOnContentList(std::function<void()> finished, u64 title_id, | ||
| 102 | std::optional<u128> user_id, | ||
| 103 | std::optional<bool> full_display) override; | ||
| 104 | void ShowSubscriptionList(std::function<void()> finished, u64 title_id, | ||
| 105 | std::optional<u128> user_id) override; | ||
| 106 | void ShowConsumableItemList(std::function<void()> finished, u64 title_id, | ||
| 107 | std::optional<u128> user_id) override; | ||
| 108 | void ShowShopHome(std::function<void()> finished, u128 user_id, bool full_display) override; | ||
| 109 | void ShowSettings(std::function<void()> finished, u128 user_id, bool full_display) override; | ||
| 110 | }; | ||
| 111 | |||
| 28 | } // namespace Core::Frontend | 112 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 3a3d3d0bf..528295ffc 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp | |||
| @@ -11,9 +11,9 @@ WebBrowserApplet::~WebBrowserApplet() = default; | |||
| 11 | 11 | ||
| 12 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; | 12 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; |
| 13 | 13 | ||
| 14 | void DefaultWebBrowserApplet::OpenPage(std::string_view filename, | 14 | void DefaultWebBrowserApplet::OpenPageLocal(std::string_view filename, |
| 15 | std::function<void()> unpack_romfs_callback, | 15 | std::function<void()> unpack_romfs_callback, |
| 16 | std::function<void()> finished_callback) { | 16 | std::function<void()> finished_callback) { |
| 17 | LOG_INFO(Service_AM, | 17 | LOG_INFO(Service_AM, |
| 18 | "(STUBBED) called - No suitable web browser implementation found to open website page " | 18 | "(STUBBED) called - No suitable web browser implementation found to open website page " |
| 19 | "at '{}'!", | 19 | "at '{}'!", |
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index f952856af..110e33bc4 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h | |||
| @@ -13,16 +13,16 @@ class WebBrowserApplet { | |||
| 13 | public: | 13 | public: |
| 14 | virtual ~WebBrowserApplet(); | 14 | virtual ~WebBrowserApplet(); |
| 15 | 15 | ||
| 16 | virtual void OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback, | 16 | virtual void OpenPageLocal(std::string_view url, std::function<void()> unpack_romfs_callback, |
| 17 | std::function<void()> finished_callback) = 0; | 17 | std::function<void()> finished_callback) = 0; |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | class DefaultWebBrowserApplet final : public WebBrowserApplet { | 20 | class DefaultWebBrowserApplet final : public WebBrowserApplet { |
| 21 | public: | 21 | public: |
| 22 | ~DefaultWebBrowserApplet() override; | 22 | ~DefaultWebBrowserApplet() override; |
| 23 | 23 | ||
| 24 | void OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback, | 24 | void OpenPageLocal(std::string_view url, std::function<void()> unpack_romfs_callback, |
| 25 | std::function<void()> finished_callback) override; | 25 | std::function<void()> finished_callback) override; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | } // namespace Core::Frontend | 28 | } // namespace Core::Frontend |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4a7bf4acb..33cebb48b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -887,7 +887,9 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { | |||
| 887 | rb.Push(RESULT_SUCCESS); | 887 | rb.Push(RESULT_SUCCESS); |
| 888 | } | 888 | } |
| 889 | 889 | ||
| 890 | ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") { | 890 | ILibraryAppletCreator::ILibraryAppletCreator(u64 current_process_title_id) |
| 891 | : ServiceFramework("ILibraryAppletCreator"), | ||
| 892 | current_process_title_id(current_process_title_id) { | ||
| 891 | static const FunctionInfo functions[] = { | 893 | static const FunctionInfo functions[] = { |
| 892 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, | 894 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, |
| 893 | {1, nullptr, "TerminateAllLibraryApplets"}, | 895 | {1, nullptr, "TerminateAllLibraryApplets"}, |
| @@ -910,7 +912,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) | |||
| 910 | static_cast<u32>(applet_id), applet_mode); | 912 | static_cast<u32>(applet_id), applet_mode); |
| 911 | 913 | ||
| 912 | const auto& applet_manager{Core::System::GetInstance().GetAppletManager()}; | 914 | const auto& applet_manager{Core::System::GetInstance().GetAppletManager()}; |
| 913 | const auto applet = applet_manager.GetApplet(applet_id); | 915 | const auto applet = applet_manager.GetApplet(applet_id, current_process_title_id); |
| 914 | 916 | ||
| 915 | if (applet == nullptr) { | 917 | if (applet == nullptr) { |
| 916 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id)); | 918 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id)); |
| @@ -1234,13 +1236,13 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) { | |||
| 1234 | } | 1236 | } |
| 1235 | 1237 | ||
| 1236 | void InstallInterfaces(SM::ServiceManager& service_manager, | 1238 | void InstallInterfaces(SM::ServiceManager& service_manager, |
| 1237 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger) { | 1239 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) { |
| 1238 | auto message_queue = std::make_shared<AppletMessageQueue>(); | 1240 | auto message_queue = std::make_shared<AppletMessageQueue>(); |
| 1239 | message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on | 1241 | message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on |
| 1240 | // game boot | 1242 | // game boot |
| 1241 | 1243 | ||
| 1242 | std::make_shared<AppletAE>(nvflinger, message_queue)->InstallAsService(service_manager); | 1244 | std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager); |
| 1243 | std::make_shared<AppletOE>(nvflinger, message_queue)->InstallAsService(service_manager); | 1245 | std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager); |
| 1244 | std::make_shared<IdleSys>()->InstallAsService(service_manager); | 1246 | std::make_shared<IdleSys>()->InstallAsService(service_manager); |
| 1245 | std::make_shared<OMM>()->InstallAsService(service_manager); | 1247 | std::make_shared<OMM>()->InstallAsService(service_manager); |
| 1246 | std::make_shared<SPSM>()->InstallAsService(service_manager); | 1248 | std::make_shared<SPSM>()->InstallAsService(service_manager); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 1fa069e56..4ea609d23 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -201,13 +201,15 @@ private: | |||
| 201 | 201 | ||
| 202 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | 202 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { |
| 203 | public: | 203 | public: |
| 204 | ILibraryAppletCreator(); | 204 | ILibraryAppletCreator(u64 current_process_title_id); |
| 205 | ~ILibraryAppletCreator() override; | 205 | ~ILibraryAppletCreator() override; |
| 206 | 206 | ||
| 207 | private: | 207 | private: |
| 208 | void CreateLibraryApplet(Kernel::HLERequestContext& ctx); | 208 | void CreateLibraryApplet(Kernel::HLERequestContext& ctx); |
| 209 | void CreateStorage(Kernel::HLERequestContext& ctx); | 209 | void CreateStorage(Kernel::HLERequestContext& ctx); |
| 210 | void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); | 210 | void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); |
| 211 | |||
| 212 | u64 current_process_title_id; | ||
| 211 | }; | 213 | }; |
| 212 | 214 | ||
| 213 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | 215 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { |
| @@ -264,7 +266,7 @@ public: | |||
| 264 | 266 | ||
| 265 | /// Registers all AM services with the specified service manager. | 267 | /// Registers all AM services with the specified service manager. |
| 266 | void InstallInterfaces(SM::ServiceManager& service_manager, | 268 | void InstallInterfaces(SM::ServiceManager& service_manager, |
| 267 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger); | 269 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system); |
| 268 | 270 | ||
| 269 | } // namespace AM | 271 | } // namespace AM |
| 270 | } // namespace Service | 272 | } // namespace Service |
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 488add8e7..fe5beb8f9 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/process.h" | ||
| 7 | #include "core/hle/service/am/am.h" | 8 | #include "core/hle/service/am/am.h" |
| 8 | #include "core/hle/service/am/applet_ae.h" | 9 | #include "core/hle/service/am/applet_ae.h" |
| 9 | #include "core/hle/service/nvflinger/nvflinger.h" | 10 | #include "core/hle/service/nvflinger/nvflinger.h" |
| @@ -13,9 +14,10 @@ namespace Service::AM { | |||
| 13 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | 14 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { |
| 14 | public: | 15 | public: |
| 15 | explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 16 | explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue) | 17 | std::shared_ptr<AppletMessageQueue> msg_queue, |
| 18 | Core::System& system) | ||
| 17 | : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), | 19 | : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), |
| 18 | msg_queue(std::move(msg_queue)) { | 20 | msg_queue(std::move(msg_queue)), system(system) { |
| 19 | // clang-format off | 21 | // clang-format off |
| 20 | static const FunctionInfo functions[] = { | 22 | static const FunctionInfo functions[] = { |
| 21 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | 23 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, |
| @@ -96,7 +98,7 @@ private: | |||
| 96 | 98 | ||
| 97 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 99 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 98 | rb.Push(RESULT_SUCCESS); | 100 | rb.Push(RESULT_SUCCESS); |
| 99 | rb.PushIpcInterface<ILibraryAppletCreator>(); | 101 | rb.PushIpcInterface<ILibraryAppletCreator>(system.CurrentProcess()->GetTitleID()); |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { | 104 | void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { |
| @@ -109,14 +111,15 @@ private: | |||
| 109 | 111 | ||
| 110 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 112 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 111 | std::shared_ptr<AppletMessageQueue> msg_queue; | 113 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 114 | Core::System& system; | ||
| 112 | }; | 115 | }; |
| 113 | 116 | ||
| 114 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | 117 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { |
| 115 | public: | 118 | public: |
| 116 | explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 119 | explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 117 | std::shared_ptr<AppletMessageQueue> msg_queue) | 120 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 118 | : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), | 121 | : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), |
| 119 | msg_queue(std::move(msg_queue)) { | 122 | msg_queue(std::move(msg_queue)), system(system) { |
| 120 | // clang-format off | 123 | // clang-format off |
| 121 | static const FunctionInfo functions[] = { | 124 | static const FunctionInfo functions[] = { |
| 122 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | 125 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, |
| @@ -191,7 +194,7 @@ private: | |||
| 191 | 194 | ||
| 192 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 195 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 193 | rb.Push(RESULT_SUCCESS); | 196 | rb.Push(RESULT_SUCCESS); |
| 194 | rb.PushIpcInterface<ILibraryAppletCreator>(); | 197 | rb.PushIpcInterface<ILibraryAppletCreator>(system.CurrentProcess()->GetTitleID()); |
| 195 | } | 198 | } |
| 196 | 199 | ||
| 197 | void GetHomeMenuFunctions(Kernel::HLERequestContext& ctx) { | 200 | void GetHomeMenuFunctions(Kernel::HLERequestContext& ctx) { |
| @@ -219,6 +222,7 @@ private: | |||
| 219 | } | 222 | } |
| 220 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 223 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 221 | std::shared_ptr<AppletMessageQueue> msg_queue; | 224 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 225 | Core::System& system; | ||
| 222 | }; | 226 | }; |
| 223 | 227 | ||
| 224 | void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { | 228 | void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { |
| @@ -226,7 +230,7 @@ void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { | |||
| 226 | 230 | ||
| 227 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 231 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 228 | rb.Push(RESULT_SUCCESS); | 232 | rb.Push(RESULT_SUCCESS); |
| 229 | rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue); | 233 | rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue, system); |
| 230 | } | 234 | } |
| 231 | 235 | ||
| 232 | void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { | 236 | void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { |
| @@ -234,7 +238,7 @@ void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { | |||
| 234 | 238 | ||
| 235 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 239 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 236 | rb.Push(RESULT_SUCCESS); | 240 | rb.Push(RESULT_SUCCESS); |
| 237 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); | 241 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); |
| 238 | } | 242 | } |
| 239 | 243 | ||
| 240 | void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { | 244 | void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { |
| @@ -242,13 +246,13 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { | |||
| 242 | 246 | ||
| 243 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 247 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 244 | rb.Push(RESULT_SUCCESS); | 248 | rb.Push(RESULT_SUCCESS); |
| 245 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); | 249 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); |
| 246 | } | 250 | } |
| 247 | 251 | ||
| 248 | AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 252 | AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 249 | std::shared_ptr<AppletMessageQueue> msg_queue) | 253 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 250 | : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), | 254 | : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), |
| 251 | msg_queue(std::move(msg_queue)) { | 255 | msg_queue(std::move(msg_queue)), system(system) { |
| 252 | // clang-format off | 256 | // clang-format off |
| 253 | static const FunctionInfo functions[] = { | 257 | static const FunctionInfo functions[] = { |
| 254 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, | 258 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, |
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 902db2665..9e006cd9d 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h | |||
| @@ -18,7 +18,7 @@ namespace AM { | |||
| 18 | class AppletAE final : public ServiceFramework<AppletAE> { | 18 | class AppletAE final : public ServiceFramework<AppletAE> { |
| 19 | public: | 19 | public: |
| 20 | explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 20 | explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 21 | std::shared_ptr<AppletMessageQueue> msg_queue); | 21 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); |
| 22 | ~AppletAE() override; | 22 | ~AppletAE() override; |
| 23 | 23 | ||
| 24 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; | 24 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; |
| @@ -30,6 +30,7 @@ private: | |||
| 30 | 30 | ||
| 31 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 31 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 32 | std::shared_ptr<AppletMessageQueue> msg_queue; | 32 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 33 | Core::System& system; | ||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | } // namespace AM | 36 | } // namespace AM |
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index d3a0a1568..6e255fe95 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/process.h" | ||
| 7 | #include "core/hle/service/am/am.h" | 8 | #include "core/hle/service/am/am.h" |
| 8 | #include "core/hle/service/am/applet_oe.h" | 9 | #include "core/hle/service/am/applet_oe.h" |
| 9 | #include "core/hle/service/nvflinger/nvflinger.h" | 10 | #include "core/hle/service/nvflinger/nvflinger.h" |
| @@ -13,9 +14,9 @@ namespace Service::AM { | |||
| 13 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | 14 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { |
| 14 | public: | 15 | public: |
| 15 | explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 16 | explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue) | 17 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 17 | : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), | 18 | : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), |
| 18 | msg_queue(std::move(msg_queue)) { | 19 | msg_queue(std::move(msg_queue)), system(system) { |
| 19 | // clang-format off | 20 | // clang-format off |
| 20 | static const FunctionInfo functions[] = { | 21 | static const FunctionInfo functions[] = { |
| 21 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | 22 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, |
| @@ -87,7 +88,7 @@ private: | |||
| 87 | 88 | ||
| 88 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 89 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 89 | rb.Push(RESULT_SUCCESS); | 90 | rb.Push(RESULT_SUCCESS); |
| 90 | rb.PushIpcInterface<ILibraryAppletCreator>(); | 91 | rb.PushIpcInterface<ILibraryAppletCreator>(system.CurrentProcess()->GetTitleID()); |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { | 94 | void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { |
| @@ -100,6 +101,7 @@ private: | |||
| 100 | 101 | ||
| 101 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 102 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 102 | std::shared_ptr<AppletMessageQueue> msg_queue; | 103 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 104 | Core::System& system; | ||
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 105 | void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { | 107 | void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { |
| @@ -107,13 +109,13 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { | |||
| 107 | 109 | ||
| 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 110 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 109 | rb.Push(RESULT_SUCCESS); | 111 | rb.Push(RESULT_SUCCESS); |
| 110 | rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue); | 112 | rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system); |
| 111 | } | 113 | } |
| 112 | 114 | ||
| 113 | AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 115 | AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 114 | std::shared_ptr<AppletMessageQueue> msg_queue) | 116 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 115 | : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), | 117 | : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), |
| 116 | msg_queue(std::move(msg_queue)) { | 118 | msg_queue(std::move(msg_queue)), system(system) { |
| 117 | static const FunctionInfo functions[] = { | 119 | static const FunctionInfo functions[] = { |
| 118 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, | 120 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, |
| 119 | }; | 121 | }; |
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index bbd0108ef..22c05419d 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h | |||
| @@ -18,7 +18,7 @@ namespace AM { | |||
| 18 | class AppletOE final : public ServiceFramework<AppletOE> { | 18 | class AppletOE final : public ServiceFramework<AppletOE> { |
| 19 | public: | 19 | public: |
| 20 | explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 20 | explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |
| 21 | std::shared_ptr<AppletMessageQueue> msg_queue); | 21 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); |
| 22 | ~AppletOE() override; | 22 | ~AppletOE() override; |
| 23 | 23 | ||
| 24 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; | 24 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; |
| @@ -28,6 +28,7 @@ private: | |||
| 28 | 28 | ||
| 29 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 29 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 30 | std::shared_ptr<AppletMessageQueue> msg_queue; | 30 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 31 | Core::System& system; | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | } // namespace AM | 34 | } // namespace AM |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index e3e4ead03..6bdba2468 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -139,12 +139,14 @@ void Applet::Initialize() { | |||
| 139 | 139 | ||
| 140 | AppletFrontendSet::AppletFrontendSet() = default; | 140 | AppletFrontendSet::AppletFrontendSet() = default; |
| 141 | 141 | ||
| 142 | AppletFrontendSet::AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, | 142 | AppletFrontendSet::AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, |
| 143 | ProfileSelect profile_select, | 143 | PhotoViewer photo_viewer, ProfileSelect profile_select, |
| 144 | SoftwareKeyboard software_keyboard, WebBrowser web_browser) | 144 | SoftwareKeyboard software_keyboard, WebBrowser web_browser, |
| 145 | : error{std::move(error)}, photo_viewer{std::move(photo_viewer)}, profile_select{std::move( | 145 | ECommerceApplet e_commerce) |
| 146 | profile_select)}, | 146 | : parental_controls{std::move(parental_controls)}, error{std::move(error)}, |
| 147 | software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)} {} | 147 | photo_viewer{std::move(photo_viewer)}, profile_select{std::move(profile_select)}, |
| 148 | software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)}, | ||
| 149 | e_commerce{std::move(e_commerce)} {} | ||
| 148 | 150 | ||
| 149 | AppletFrontendSet::~AppletFrontendSet() = default; | 151 | AppletFrontendSet::~AppletFrontendSet() = default; |
| 150 | 152 | ||
| @@ -157,6 +159,8 @@ AppletManager::AppletManager() = default; | |||
| 157 | AppletManager::~AppletManager() = default; | 159 | AppletManager::~AppletManager() = default; |
| 158 | 160 | ||
| 159 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | 161 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { |
| 162 | if (set.parental_controls != nullptr) | ||
| 163 | frontend.parental_controls = std::move(set.parental_controls); | ||
| 160 | if (set.error != nullptr) | 164 | if (set.error != nullptr) |
| 161 | frontend.error = std::move(set.error); | 165 | frontend.error = std::move(set.error); |
| 162 | if (set.photo_viewer != nullptr) | 166 | if (set.photo_viewer != nullptr) |
| @@ -167,17 +171,21 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | |||
| 167 | frontend.software_keyboard = std::move(set.software_keyboard); | 171 | frontend.software_keyboard = std::move(set.software_keyboard); |
| 168 | if (set.web_browser != nullptr) | 172 | if (set.web_browser != nullptr) |
| 169 | frontend.web_browser = std::move(set.web_browser); | 173 | frontend.web_browser = std::move(set.web_browser); |
| 174 | if (set.e_commerce != nullptr) | ||
| 175 | frontend.e_commerce = std::move(set.e_commerce); | ||
| 170 | } | 176 | } |
| 171 | 177 | ||
| 172 | void AppletManager::SetDefaultAppletFrontendSet() { | 178 | void AppletManager::SetDefaultAppletFrontendSet() { |
| 173 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); | 179 | ClearAll(); |
| 174 | frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); | 180 | SetDefaultAppletsIfMissing(); |
| 175 | frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>(); | ||
| 176 | frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>(); | ||
| 177 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | ||
| 178 | } | 181 | } |
| 179 | 182 | ||
| 180 | void AppletManager::SetDefaultAppletsIfMissing() { | 183 | void AppletManager::SetDefaultAppletsIfMissing() { |
| 184 | if (frontend.parental_controls == nullptr) { | ||
| 185 | frontend.parental_controls = | ||
| 186 | std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); | ||
| 187 | } | ||
| 188 | |||
| 181 | if (frontend.error == nullptr) { | 189 | if (frontend.error == nullptr) { |
| 182 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); | 190 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); |
| 183 | } | 191 | } |
| @@ -198,14 +206,20 @@ void AppletManager::SetDefaultAppletsIfMissing() { | |||
| 198 | if (frontend.web_browser == nullptr) { | 206 | if (frontend.web_browser == nullptr) { |
| 199 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | 207 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); |
| 200 | } | 208 | } |
| 209 | |||
| 210 | if (frontend.e_commerce == nullptr) { | ||
| 211 | frontend.e_commerce = std::make_unique<Core::Frontend::DefaultECommerceApplet>(); | ||
| 212 | } | ||
| 201 | } | 213 | } |
| 202 | 214 | ||
| 203 | void AppletManager::ClearAll() { | 215 | void AppletManager::ClearAll() { |
| 204 | frontend = {}; | 216 | frontend = {}; |
| 205 | } | 217 | } |
| 206 | 218 | ||
| 207 | std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { | 219 | std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, u64 current_process_title_id) const { |
| 208 | switch (id) { | 220 | switch (id) { |
| 221 | case AppletId::Auth: | ||
| 222 | return std::make_shared<Auth>(*frontend.parental_controls); | ||
| 209 | case AppletId::Error: | 223 | case AppletId::Error: |
| 210 | return std::make_shared<Error>(*frontend.error); | 224 | return std::make_shared<Error>(*frontend.error); |
| 211 | case AppletId::ProfileSelect: | 225 | case AppletId::ProfileSelect: |
| @@ -214,8 +228,11 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { | |||
| 214 | return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard); | 228 | return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard); |
| 215 | case AppletId::PhotoViewer: | 229 | case AppletId::PhotoViewer: |
| 216 | return std::make_shared<PhotoViewer>(*frontend.photo_viewer); | 230 | return std::make_shared<PhotoViewer>(*frontend.photo_viewer); |
| 231 | case AppletId::LibAppletShop: | ||
| 232 | return std::make_shared<WebBrowser>(*frontend.web_browser, current_process_title_id, | ||
| 233 | frontend.e_commerce.get()); | ||
| 217 | case AppletId::LibAppletOff: | 234 | case AppletId::LibAppletOff: |
| 218 | return std::make_shared<WebBrowser>(*frontend.web_browser); | 235 | return std::make_shared<WebBrowser>(*frontend.web_browser, current_process_title_id); |
| 219 | default: | 236 | default: |
| 220 | UNIMPLEMENTED_MSG( | 237 | UNIMPLEMENTED_MSG( |
| 221 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", | 238 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", |
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 05ae739ca..adc973dad 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -13,7 +13,9 @@ | |||
| 13 | union ResultCode; | 13 | union ResultCode; |
| 14 | 14 | ||
| 15 | namespace Core::Frontend { | 15 | namespace Core::Frontend { |
| 16 | class ECommerceApplet; | ||
| 16 | class ErrorApplet; | 17 | class ErrorApplet; |
| 18 | class ParentalControlsApplet; | ||
| 17 | class PhotoViewerApplet; | 19 | class PhotoViewerApplet; |
| 18 | class ProfileSelectApplet; | 20 | class ProfileSelectApplet; |
| 19 | class SoftwareKeyboardApplet; | 21 | class SoftwareKeyboardApplet; |
| @@ -145,15 +147,19 @@ protected: | |||
| 145 | }; | 147 | }; |
| 146 | 148 | ||
| 147 | struct AppletFrontendSet { | 149 | struct AppletFrontendSet { |
| 150 | using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; | ||
| 148 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; | 151 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; |
| 149 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; | 152 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; |
| 150 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; | 153 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; |
| 151 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; | 154 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; |
| 152 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; | 155 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; |
| 156 | using ECommerceApplet = std::unique_ptr<Core::Frontend::ECommerceApplet>; | ||
| 153 | 157 | ||
| 154 | AppletFrontendSet(); | 158 | AppletFrontendSet(); |
| 155 | AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, ProfileSelect profile_select, | 159 | AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, |
| 156 | SoftwareKeyboard software_keyboard, WebBrowser web_browser); | 160 | PhotoViewer photo_viewer, ProfileSelect profile_select, |
| 161 | SoftwareKeyboard software_keyboard, WebBrowser web_browser, | ||
| 162 | ECommerceApplet e_commerce); | ||
| 157 | ~AppletFrontendSet(); | 163 | ~AppletFrontendSet(); |
| 158 | 164 | ||
| 159 | AppletFrontendSet(const AppletFrontendSet&) = delete; | 165 | AppletFrontendSet(const AppletFrontendSet&) = delete; |
| @@ -162,11 +168,13 @@ struct AppletFrontendSet { | |||
| 162 | AppletFrontendSet(AppletFrontendSet&&) noexcept; | 168 | AppletFrontendSet(AppletFrontendSet&&) noexcept; |
| 163 | AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; | 169 | AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; |
| 164 | 170 | ||
| 171 | ParentalControlsApplet parental_controls; | ||
| 165 | ErrorApplet error; | 172 | ErrorApplet error; |
| 166 | PhotoViewer photo_viewer; | 173 | PhotoViewer photo_viewer; |
| 167 | ProfileSelect profile_select; | 174 | ProfileSelect profile_select; |
| 168 | SoftwareKeyboard software_keyboard; | 175 | SoftwareKeyboard software_keyboard; |
| 169 | WebBrowser web_browser; | 176 | WebBrowser web_browser; |
| 177 | ECommerceApplet e_commerce; | ||
| 170 | }; | 178 | }; |
| 171 | 179 | ||
| 172 | class AppletManager { | 180 | class AppletManager { |
| @@ -179,7 +187,7 @@ public: | |||
| 179 | void SetDefaultAppletsIfMissing(); | 187 | void SetDefaultAppletsIfMissing(); |
| 180 | void ClearAll(); | 188 | void ClearAll(); |
| 181 | 189 | ||
| 182 | std::shared_ptr<Applet> GetApplet(AppletId id) const; | 190 | std::shared_ptr<Applet> GetApplet(AppletId id, u64 current_process_title_id) const; |
| 183 | 191 | ||
| 184 | private: | 192 | private: |
| 185 | AppletFrontendSet frontend; | 193 | AppletFrontendSet frontend; |
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 54c155dd8..e0def8dff 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | namespace Service::AM::Applets { | 18 | namespace Service::AM::Applets { |
| 19 | 19 | ||
| 20 | constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; | ||
| 21 | |||
| 20 | static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { | 22 | static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { |
| 21 | std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet(); | 23 | std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet(); |
| 22 | for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { | 24 | for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { |
| @@ -35,6 +37,120 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) | |||
| 35 | } | 37 | } |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 40 | Auth::Auth(Core::Frontend::ParentalControlsApplet& frontend) : frontend(frontend) {} | ||
| 41 | |||
| 42 | Auth::~Auth() = default; | ||
| 43 | |||
| 44 | void Auth::Initialize() { | ||
| 45 | Applet::Initialize(); | ||
| 46 | complete = false; | ||
| 47 | |||
| 48 | const auto storage = broker.PopNormalDataToApplet(); | ||
| 49 | ASSERT(storage != nullptr); | ||
| 50 | const auto data = storage->GetData(); | ||
| 51 | ASSERT(data.size() >= 0xC); | ||
| 52 | |||
| 53 | struct Arg { | ||
| 54 | INSERT_PADDING_BYTES(4); | ||
| 55 | AuthAppletType type; | ||
| 56 | u8 arg0; | ||
| 57 | u8 arg1; | ||
| 58 | u8 arg2; | ||
| 59 | INSERT_PADDING_BYTES(1); | ||
| 60 | }; | ||
| 61 | static_assert(sizeof(Arg) == 0xC, "Arg (AuthApplet) has incorrect size."); | ||
| 62 | |||
| 63 | Arg arg{}; | ||
| 64 | std::memcpy(&arg, data.data(), sizeof(Arg)); | ||
| 65 | |||
| 66 | type = arg.type; | ||
| 67 | arg0 = arg.arg0; | ||
| 68 | arg1 = arg.arg1; | ||
| 69 | arg2 = arg.arg2; | ||
| 70 | } | ||
| 71 | |||
| 72 | bool Auth::TransactionComplete() const { | ||
| 73 | return complete; | ||
| 74 | } | ||
| 75 | |||
| 76 | ResultCode Auth::GetStatus() const { | ||
| 77 | return successful ? RESULT_SUCCESS : ERROR_INVALID_PIN; | ||
| 78 | } | ||
| 79 | |||
| 80 | void Auth::ExecuteInteractive() { | ||
| 81 | UNREACHABLE_MSG("Unexpected interactive applet data."); | ||
| 82 | } | ||
| 83 | |||
| 84 | void Auth::Execute() { | ||
| 85 | if (complete) { | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 89 | const auto unimplemented_log = [this] { | ||
| 90 | UNIMPLEMENTED_MSG("Unimplemented Auth applet type for type={:08X}, arg0={:02X}, " | ||
| 91 | "arg1={:02X}, arg2={:02X}", | ||
| 92 | static_cast<u32>(type), arg0, arg1, arg2); | ||
| 93 | }; | ||
| 94 | |||
| 95 | switch (type) { | ||
| 96 | case AuthAppletType::ShowParentalAuthentication: { | ||
| 97 | const auto callback = [this](bool successful) { AuthFinished(successful); }; | ||
| 98 | |||
| 99 | if (arg0 == 1 && arg1 == 0 && arg2 == 1) { | ||
| 100 | // ShowAuthenticatorForConfiguration | ||
| 101 | frontend.VerifyPINForSettings(callback); | ||
| 102 | } else if (arg1 == 0 && arg2 == 0) { | ||
| 103 | // ShowParentalAuthentication(bool) | ||
| 104 | frontend.VerifyPIN(callback, static_cast<bool>(arg0)); | ||
| 105 | } else { | ||
| 106 | unimplemented_log(); | ||
| 107 | } | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | case AuthAppletType::RegisterParentalPasscode: { | ||
| 111 | const auto callback = [this] { AuthFinished(true); }; | ||
| 112 | |||
| 113 | if (arg0 == 0 && arg1 == 0 && arg2 == 0) { | ||
| 114 | // RegisterParentalPasscode | ||
| 115 | frontend.RegisterPIN(callback); | ||
| 116 | } else { | ||
| 117 | unimplemented_log(); | ||
| 118 | } | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | case AuthAppletType::ChangeParentalPasscode: { | ||
| 122 | const auto callback = [this] { AuthFinished(true); }; | ||
| 123 | |||
| 124 | if (arg0 == 0 && arg1 == 0 && arg2 == 0) { | ||
| 125 | // ChangeParentalPasscode | ||
| 126 | frontend.ChangePIN(callback); | ||
| 127 | } else { | ||
| 128 | unimplemented_log(); | ||
| 129 | } | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | default: | ||
| 133 | unimplemented_log(); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | void Auth::AuthFinished(bool successful) { | ||
| 138 | this->successful = successful; | ||
| 139 | |||
| 140 | struct Return { | ||
| 141 | ResultCode result_code; | ||
| 142 | }; | ||
| 143 | static_assert(sizeof(Return) == 0x4, "Return (AuthApplet) has incorrect size."); | ||
| 144 | |||
| 145 | Return return_{GetStatus()}; | ||
| 146 | |||
| 147 | std::vector<u8> out(sizeof(Return)); | ||
| 148 | std::memcpy(out.data(), &return_, sizeof(Return)); | ||
| 149 | |||
| 150 | broker.PushNormalDataFromApplet(IStorage{out}); | ||
| 151 | broker.SignalStateChanged(); | ||
| 152 | } | ||
| 153 | |||
| 38 | PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {} | 154 | PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {} |
| 39 | 155 | ||
| 40 | PhotoViewer::~PhotoViewer() = default; | 156 | PhotoViewer::~PhotoViewer() = default; |
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index fb68a2543..0da252044 100644 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h | |||
| @@ -8,6 +8,36 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::AM::Applets { | 9 | namespace Service::AM::Applets { |
| 10 | 10 | ||
| 11 | enum class AuthAppletType : u32 { | ||
| 12 | ShowParentalAuthentication, | ||
| 13 | RegisterParentalPasscode, | ||
| 14 | ChangeParentalPasscode, | ||
| 15 | }; | ||
| 16 | |||
| 17 | class Auth final : public Applet { | ||
| 18 | public: | ||
| 19 | explicit Auth(Core::Frontend::ParentalControlsApplet& frontend); | ||
| 20 | ~Auth() override; | ||
| 21 | |||
| 22 | void Initialize() override; | ||
| 23 | bool TransactionComplete() const override; | ||
| 24 | ResultCode GetStatus() const override; | ||
| 25 | void ExecuteInteractive() override; | ||
| 26 | void Execute() override; | ||
| 27 | |||
| 28 | void AuthFinished(bool successful = true); | ||
| 29 | |||
| 30 | private: | ||
| 31 | Core::Frontend::ParentalControlsApplet& frontend; | ||
| 32 | bool complete = false; | ||
| 33 | bool successful = false; | ||
| 34 | |||
| 35 | AuthAppletType type = AuthAppletType::ShowParentalAuthentication; | ||
| 36 | u8 arg0 = 0; | ||
| 37 | u8 arg1 = 0; | ||
| 38 | u8 arg2 = 0; | ||
| 39 | }; | ||
| 40 | |||
| 11 | enum class PhotoViewerAppletMode : u8 { | 41 | enum class PhotoViewerAppletMode : u8 { |
| 12 | CurrentApp = 0, | 42 | CurrentApp = 0, |
| 13 | AllApps = 1, | 43 | AllApps = 1, |
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 7878f5136..2762e0653 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -19,7 +19,9 @@ | |||
| 19 | #include "core/file_sys/nca_metadata.h" | 19 | #include "core/file_sys/nca_metadata.h" |
| 20 | #include "core/file_sys/registered_cache.h" | 20 | #include "core/file_sys/registered_cache.h" |
| 21 | #include "core/file_sys/romfs.h" | 21 | #include "core/file_sys/romfs.h" |
| 22 | #include "core/file_sys/system_archive/system_archive.h" | ||
| 22 | #include "core/file_sys/vfs_types.h" | 23 | #include "core/file_sys/vfs_types.h" |
| 24 | #include "core/frontend/applets/general_frontend.h" | ||
| 23 | #include "core/frontend/applets/web_browser.h" | 25 | #include "core/frontend/applets/web_browser.h" |
| 24 | #include "core/hle/kernel/process.h" | 26 | #include "core/hle/kernel/process.h" |
| 25 | #include "core/hle/service/am/applets/web_browser.h" | 27 | #include "core/hle/service/am/applets/web_browser.h" |
| @@ -28,74 +30,187 @@ | |||
| 28 | 30 | ||
| 29 | namespace Service::AM::Applets { | 31 | namespace Service::AM::Applets { |
| 30 | 32 | ||
| 31 | // TODO(DarkLordZach): There are other arguments in the WebBuffer structure that are currently not | 33 | enum class WebArgTLVType : u16 { |
| 32 | // parsed, for example footer mode and left stick mode. Some of these are not particularly relevant, | 34 | InitialURL = 0x1, |
| 33 | // but some may be worth an implementation. | 35 | ShopArgumentsURL = 0x2, ///< TODO(DarkLordZach): This is not the official name. |
| 34 | constexpr u16 WEB_ARGUMENT_URL_TYPE = 0x6; | 36 | CallbackURL = 0x3, |
| 37 | CallbackableURL = 0x4, | ||
| 38 | ApplicationID = 0x5, | ||
| 39 | DocumentPath = 0x6, | ||
| 40 | DocumentKind = 0x7, | ||
| 41 | SystemDataID = 0x8, | ||
| 42 | ShareStartPage = 0x9, | ||
| 43 | Whitelist = 0xA, | ||
| 44 | News = 0xB, | ||
| 45 | UserID = 0xE, | ||
| 46 | AlbumEntry0 = 0xF, | ||
| 47 | ScreenShotEnabled = 0x10, | ||
| 48 | EcClientCertEnabled = 0x11, | ||
| 49 | Unk12 = 0x12, | ||
| 50 | PlayReportEnabled = 0x13, | ||
| 51 | Unk14 = 0x14, | ||
| 52 | Unk15 = 0x15, | ||
| 53 | BootDisplayKind = 0x17, | ||
| 54 | BackgroundKind = 0x18, | ||
| 55 | FooterEnabled = 0x19, | ||
| 56 | PointerEnabled = 0x1A, | ||
| 57 | LeftStickMode = 0x1B, | ||
| 58 | KeyRepeatFrame1 = 0x1C, | ||
| 59 | KeyRepeatFrame2 = 0x1D, | ||
| 60 | BootAsMediaPlayerInv = 0x1E, | ||
| 61 | DisplayUrlKind = 0x1F, | ||
| 62 | BootAsMediaPlayer = 0x21, | ||
| 63 | ShopJumpEnabled = 0x22, | ||
| 64 | MediaAutoPlayEnabled = 0x23, | ||
| 65 | LobbyParameter = 0x24, | ||
| 66 | ApplicationAlbumEntry = 0x26, | ||
| 67 | JsExtensionEnabled = 0x27, | ||
| 68 | AdditionalCommentText = 0x28, | ||
| 69 | TouchEnabledOnContents = 0x29, | ||
| 70 | UserAgentAdditionalString = 0x2A, | ||
| 71 | AdditionalMediaData0 = 0x2B, | ||
| 72 | MediaPlayerAutoCloseEnabled = 0x2C, | ||
| 73 | PageCacheEnabled = 0x2D, | ||
| 74 | WebAudioEnabled = 0x2E, | ||
| 75 | Unk2F = 0x2F, | ||
| 76 | YouTubeVideoWhitelist = 0x31, | ||
| 77 | FooterFixedKind = 0x32, | ||
| 78 | PageFadeEnabled = 0x33, | ||
| 79 | MediaCreatorApplicationRatingAge = 0x34, | ||
| 80 | BootLoadingIconEnabled = 0x35, | ||
| 81 | PageScrollIndicationEnabled = 0x36, | ||
| 82 | MediaPlayerSpeedControlEnabled = 0x37, | ||
| 83 | AlbumEntry1 = 0x38, | ||
| 84 | AlbumEntry2 = 0x39, | ||
| 85 | AlbumEntry3 = 0x3A, | ||
| 86 | AdditionalMediaData1 = 0x3B, | ||
| 87 | AdditionalMediaData2 = 0x3C, | ||
| 88 | AdditionalMediaData3 = 0x3D, | ||
| 89 | BootFooterButton = 0x3E, | ||
| 90 | OverrideWebAudioVolume = 0x3F, | ||
| 91 | OverrideMediaAudioVolume = 0x40, | ||
| 92 | BootMode = 0x41, | ||
| 93 | WebSessionEnabled = 0x42, | ||
| 94 | }; | ||
| 95 | |||
| 96 | enum class ShimKind : u32 { | ||
| 97 | Shop = 1, | ||
| 98 | Login = 2, | ||
| 99 | Offline = 3, | ||
| 100 | Share = 4, | ||
| 101 | Web = 5, | ||
| 102 | Wifi = 6, | ||
| 103 | Lobby = 7, | ||
| 104 | }; | ||
| 105 | |||
| 106 | enum class ShopWebTarget { | ||
| 107 | ApplicationInfo, | ||
| 108 | AddOnContentList, | ||
| 109 | SubscriptionList, | ||
| 110 | ConsumableItemList, | ||
| 111 | Home, | ||
| 112 | Settings, | ||
| 113 | }; | ||
| 114 | |||
| 115 | namespace { | ||
| 35 | 116 | ||
| 36 | struct WebBufferHeader { | 117 | constexpr std::size_t SHIM_KIND_COUNT = 0x8; |
| 118 | |||
| 119 | struct WebArgHeader { | ||
| 37 | u16 count; | 120 | u16 count; |
| 38 | INSERT_PADDING_BYTES(6); | 121 | INSERT_PADDING_BYTES(2); |
| 122 | ShimKind kind; | ||
| 39 | }; | 123 | }; |
| 40 | static_assert(sizeof(WebBufferHeader) == 0x8, "WebBufferHeader has incorrect size."); | 124 | static_assert(sizeof(WebArgHeader) == 0x8, "WebArgHeader has incorrect size."); |
| 41 | 125 | ||
| 42 | struct WebArgumentHeader { | 126 | struct WebArgTLV { |
| 43 | u16 type; | 127 | WebArgTLVType type; |
| 44 | u16 size; | 128 | u16 size; |
| 45 | u32 offset; | 129 | u32 offset; |
| 46 | }; | 130 | }; |
| 47 | static_assert(sizeof(WebArgumentHeader) == 0x8, "WebArgumentHeader has incorrect size."); | 131 | static_assert(sizeof(WebArgTLV) == 0x8, "WebArgTLV has incorrect size."); |
| 48 | 132 | ||
| 49 | struct WebArgumentResult { | 133 | struct WebCommonReturnValue { |
| 50 | u32 result_code; | 134 | u32 result_code; |
| 135 | INSERT_PADDING_BYTES(0x4); | ||
| 51 | std::array<char, 0x1000> last_url; | 136 | std::array<char, 0x1000> last_url; |
| 52 | u64 last_url_size; | 137 | u64 last_url_size; |
| 53 | }; | 138 | }; |
| 54 | static_assert(sizeof(WebArgumentResult) == 0x1010, "WebArgumentResult has incorrect size."); | 139 | static_assert(sizeof(WebCommonReturnValue) == 0x1010, "WebCommonReturnValue has incorrect size."); |
| 55 | 140 | ||
| 56 | static std::vector<u8> GetArgumentDataForTagType(const std::vector<u8>& data, u16 type) { | 141 | struct WebWifiPageArg { |
| 57 | WebBufferHeader header; | 142 | INSERT_PADDING_BYTES(4); |
| 58 | ASSERT(sizeof(WebBufferHeader) <= data.size()); | 143 | std::array<char, 0x100> connection_test_url; |
| 59 | std::memcpy(&header, data.data(), sizeof(WebBufferHeader)); | 144 | std::array<char, 0x400> initial_url; |
| 60 | 145 | std::array<u8, 0x10> nifm_network_uuid; | |
| 61 | u64 offset = sizeof(WebBufferHeader); | 146 | u32 nifm_requirement; |
| 62 | for (u16 i = 0; i < header.count; ++i) { | 147 | }; |
| 63 | WebArgumentHeader arg; | 148 | static_assert(sizeof(WebWifiPageArg) == 0x518, "WebWifiPageArg has incorrect size."); |
| 64 | ASSERT(offset + sizeof(WebArgumentHeader) <= data.size()); | 149 | |
| 65 | std::memcpy(&arg, data.data() + offset, sizeof(WebArgumentHeader)); | 150 | struct WebWifiReturnValue { |
| 66 | offset += sizeof(WebArgumentHeader); | 151 | INSERT_PADDING_BYTES(4); |
| 67 | 152 | u32 result; | |
| 68 | if (arg.type == type) { | 153 | }; |
| 69 | std::vector<u8> out(arg.size); | 154 | static_assert(sizeof(WebWifiReturnValue) == 0x8, "WebWifiReturnValue has incorrect size."); |
| 70 | offset += arg.offset; | 155 | |
| 71 | ASSERT(offset + arg.size <= data.size()); | 156 | enum class OfflineWebSource : u32 { |
| 72 | std::memcpy(out.data(), data.data() + offset, out.size()); | 157 | OfflineHtmlPage = 0x1, |
| 158 | ApplicationLegalInformation = 0x2, | ||
| 159 | SystemDataPage = 0x3, | ||
| 160 | }; | ||
| 161 | |||
| 162 | std::map<WebArgTLVType, std::vector<u8>> GetWebArguments(const std::vector<u8>& arg) { | ||
| 163 | if (arg.size() < sizeof(WebArgHeader)) | ||
| 164 | return {}; | ||
| 165 | |||
| 166 | WebArgHeader header{}; | ||
| 167 | std::memcpy(&header, arg.data(), sizeof(WebArgHeader)); | ||
| 168 | |||
| 169 | std::map<WebArgTLVType, std::vector<u8>> out; | ||
| 170 | u64 offset = sizeof(WebArgHeader); | ||
| 171 | for (std::size_t i = 0; i < header.count; ++i) { | ||
| 172 | if (arg.size() < (offset + sizeof(WebArgTLV))) | ||
| 73 | return out; | 173 | return out; |
| 74 | } | ||
| 75 | 174 | ||
| 76 | offset += arg.offset + arg.size; | 175 | WebArgTLV tlv{}; |
| 77 | } | 176 | std::memcpy(&tlv, arg.data() + offset, sizeof(WebArgTLV)); |
| 177 | offset += sizeof(WebArgTLV); | ||
| 78 | 178 | ||
| 79 | return {}; | 179 | offset += tlv.offset; |
| 80 | } | 180 | if (arg.size() < (offset + tlv.size)) |
| 181 | return out; | ||
| 182 | |||
| 183 | std::vector<u8> data(tlv.size); | ||
| 184 | std::memcpy(data.data(), arg.data() + offset, tlv.size); | ||
| 185 | offset += tlv.size; | ||
| 81 | 186 | ||
| 82 | static FileSys::VirtualFile GetManualRomFS() { | 187 | out.insert_or_assign(tlv.type, data); |
| 83 | auto& loader{Core::System::GetInstance().GetAppLoader()}; | 188 | } |
| 84 | 189 | ||
| 85 | FileSys::VirtualFile out; | 190 | return out; |
| 86 | if (loader.ReadManualRomFS(out) == Loader::ResultStatus::Success) | 191 | } |
| 87 | return out; | ||
| 88 | 192 | ||
| 193 | FileSys::VirtualFile GetApplicationRomFS(u64 title_id, FileSys::ContentRecordType type) { | ||
| 89 | const auto& installed{Core::System::GetInstance().GetContentProvider()}; | 194 | const auto& installed{Core::System::GetInstance().GetContentProvider()}; |
| 90 | const auto res = installed.GetEntry(Core::System::GetInstance().CurrentProcess()->GetTitleID(), | 195 | const auto res = installed.GetEntry(title_id, type); |
| 91 | FileSys::ContentRecordType::Manual); | ||
| 92 | 196 | ||
| 93 | if (res != nullptr) | 197 | if (res != nullptr) { |
| 94 | return res->GetRomFS(); | 198 | return res->GetRomFS(); |
| 199 | } | ||
| 200 | |||
| 201 | if (type == FileSys::ContentRecordType::Data) { | ||
| 202 | return FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | ||
| 203 | } | ||
| 204 | |||
| 95 | return nullptr; | 205 | return nullptr; |
| 96 | } | 206 | } |
| 97 | 207 | ||
| 98 | WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} | 208 | } // Anonymous namespace |
| 209 | |||
| 210 | WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend, u64 current_process_title_id, | ||
| 211 | Core::Frontend::ECommerceApplet* frontend_e_commerce) | ||
| 212 | : frontend(frontend), frontend_e_commerce(frontend_e_commerce), | ||
| 213 | current_process_title_id(current_process_title_id) {} | ||
| 99 | 214 | ||
| 100 | WebBrowser::~WebBrowser() = default; | 215 | WebBrowser::~WebBrowser() = default; |
| 101 | 216 | ||
| @@ -111,24 +226,12 @@ void WebBrowser::Initialize() { | |||
| 111 | ASSERT(web_arg_storage != nullptr); | 226 | ASSERT(web_arg_storage != nullptr); |
| 112 | const auto& web_arg = web_arg_storage->GetData(); | 227 | const auto& web_arg = web_arg_storage->GetData(); |
| 113 | 228 | ||
| 114 | const auto url_data = GetArgumentDataForTagType(web_arg, WEB_ARGUMENT_URL_TYPE); | 229 | ASSERT(web_arg.size() >= 0x8); |
| 115 | filename = Common::StringFromFixedZeroTerminatedBuffer( | 230 | std::memcpy(&kind, web_arg.data() + 0x4, sizeof(ShimKind)); |
| 116 | reinterpret_cast<const char*>(url_data.data()), url_data.size()); | ||
| 117 | 231 | ||
| 118 | temporary_dir = FileUtil::SanitizePath(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + | 232 | args = GetWebArguments(web_arg); |
| 119 | "web_applet_manual", | ||
| 120 | FileUtil::DirectorySeparator::PlatformDefault); | ||
| 121 | FileUtil::DeleteDirRecursively(temporary_dir); | ||
| 122 | 233 | ||
| 123 | manual_romfs = GetManualRomFS(); | 234 | InitializeInternal(); |
| 124 | if (manual_romfs == nullptr) { | ||
| 125 | status = ResultCode(-1); | ||
| 126 | LOG_ERROR(Service_AM, "Failed to find manual for current process!"); | ||
| 127 | } | ||
| 128 | |||
| 129 | filename = | ||
| 130 | FileUtil::SanitizePath(temporary_dir + DIR_SEP + "html-document" + DIR_SEP + filename, | ||
| 131 | FileUtil::DirectorySeparator::PlatformDefault); | ||
| 132 | } | 235 | } |
| 133 | 236 | ||
| 134 | bool WebBrowser::TransactionComplete() const { | 237 | bool WebBrowser::TransactionComplete() const { |
| @@ -144,24 +247,25 @@ void WebBrowser::ExecuteInteractive() { | |||
| 144 | } | 247 | } |
| 145 | 248 | ||
| 146 | void WebBrowser::Execute() { | 249 | void WebBrowser::Execute() { |
| 147 | if (complete) | 250 | if (complete) { |
| 148 | return; | 251 | return; |
| 252 | } | ||
| 149 | 253 | ||
| 150 | if (status != RESULT_SUCCESS) { | 254 | if (status != RESULT_SUCCESS) { |
| 151 | complete = true; | 255 | complete = true; |
| 152 | return; | 256 | return; |
| 153 | } | 257 | } |
| 154 | 258 | ||
| 155 | frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); | 259 | ExecuteInternal(); |
| 156 | } | 260 | } |
| 157 | 261 | ||
| 158 | void WebBrowser::UnpackRomFS() { | 262 | void WebBrowser::UnpackRomFS() { |
| 159 | if (unpacked) | 263 | if (unpacked) |
| 160 | return; | 264 | return; |
| 161 | 265 | ||
| 162 | ASSERT(manual_romfs != nullptr); | 266 | ASSERT(offline_romfs != nullptr); |
| 163 | const auto dir = | 267 | const auto dir = |
| 164 | FileSys::ExtractRomFS(manual_romfs, FileSys::RomFSExtractionType::SingleDiscard); | 268 | FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard); |
| 165 | const auto& vfs{Core::System::GetInstance().GetFilesystem()}; | 269 | const auto& vfs{Core::System::GetInstance().GetFilesystem()}; |
| 166 | const auto temp_dir = vfs->CreateDirectory(temporary_dir, FileSys::Mode::ReadWrite); | 270 | const auto temp_dir = vfs->CreateDirectory(temporary_dir, FileSys::Mode::ReadWrite); |
| 167 | FileSys::VfsRawCopyD(dir, temp_dir); | 271 | FileSys::VfsRawCopyD(dir, temp_dir); |
| @@ -172,17 +276,275 @@ void WebBrowser::UnpackRomFS() { | |||
| 172 | void WebBrowser::Finalize() { | 276 | void WebBrowser::Finalize() { |
| 173 | complete = true; | 277 | complete = true; |
| 174 | 278 | ||
| 175 | WebArgumentResult out{}; | 279 | WebCommonReturnValue out{}; |
| 176 | out.result_code = 0; | 280 | out.result_code = 0; |
| 177 | out.last_url_size = 0; | 281 | out.last_url_size = 0; |
| 178 | 282 | ||
| 179 | std::vector<u8> data(sizeof(WebArgumentResult)); | 283 | std::vector<u8> data(sizeof(WebCommonReturnValue)); |
| 180 | std::memcpy(data.data(), &out, sizeof(WebArgumentResult)); | 284 | std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue)); |
| 181 | 285 | ||
| 182 | broker.PushNormalDataFromApplet(IStorage{data}); | 286 | broker.PushNormalDataFromApplet(IStorage{data}); |
| 183 | broker.SignalStateChanged(); | 287 | broker.SignalStateChanged(); |
| 184 | 288 | ||
| 289 | if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) { | ||
| 290 | FileUtil::DeleteDirRecursively(temporary_dir); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | void WebBrowser::InitializeInternal() { | ||
| 295 | using WebAppletInitializer = void (WebBrowser::*)(); | ||
| 296 | |||
| 297 | constexpr std::array<WebAppletInitializer, SHIM_KIND_COUNT> functions{ | ||
| 298 | nullptr, &WebBrowser::InitializeShop, | ||
| 299 | nullptr, &WebBrowser::InitializeOffline, | ||
| 300 | nullptr, nullptr, | ||
| 301 | nullptr, nullptr, | ||
| 302 | }; | ||
| 303 | |||
| 304 | const auto index = static_cast<u32>(kind); | ||
| 305 | |||
| 306 | if (index > functions.size() || functions[index] == nullptr) { | ||
| 307 | LOG_ERROR(Service_AM, "Invalid shim_kind={:08X}", index); | ||
| 308 | return; | ||
| 309 | } | ||
| 310 | |||
| 311 | const auto function = functions[index]; | ||
| 312 | (this->*function)(); | ||
| 313 | } | ||
| 314 | |||
| 315 | void WebBrowser::ExecuteInternal() { | ||
| 316 | using WebAppletExecutor = void (WebBrowser::*)(); | ||
| 317 | |||
| 318 | constexpr std::array<WebAppletExecutor, SHIM_KIND_COUNT> functions{ | ||
| 319 | nullptr, &WebBrowser::ExecuteShop, | ||
| 320 | nullptr, &WebBrowser::ExecuteOffline, | ||
| 321 | nullptr, nullptr, | ||
| 322 | nullptr, nullptr, | ||
| 323 | }; | ||
| 324 | |||
| 325 | const auto index = static_cast<u32>(kind); | ||
| 326 | |||
| 327 | if (index > functions.size() || functions[index] == nullptr) { | ||
| 328 | LOG_ERROR(Service_AM, "Invalid shim_kind={:08X}", index); | ||
| 329 | return; | ||
| 330 | } | ||
| 331 | |||
| 332 | const auto function = functions[index]; | ||
| 333 | (this->*function)(); | ||
| 334 | } | ||
| 335 | |||
| 336 | void WebBrowser::InitializeShop() { | ||
| 337 | if (frontend_e_commerce == nullptr) { | ||
| 338 | LOG_ERROR(Service_AM, "Missing ECommerce Applet frontend!"); | ||
| 339 | status = ResultCode(-1); | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | |||
| 343 | const auto user_id_data = args.find(WebArgTLVType::UserID); | ||
| 344 | |||
| 345 | user_id = std::nullopt; | ||
| 346 | if (user_id_data != args.end()) { | ||
| 347 | user_id = u128{}; | ||
| 348 | std::memcpy(user_id->data(), user_id_data->second.data(), sizeof(u128)); | ||
| 349 | } | ||
| 350 | |||
| 351 | const auto url = args.find(WebArgTLVType::ShopArgumentsURL); | ||
| 352 | |||
| 353 | if (url == args.end()) { | ||
| 354 | LOG_ERROR(Service_AM, "Missing EShop Arguments URL for initialization!"); | ||
| 355 | status = ResultCode(-1); | ||
| 356 | return; | ||
| 357 | } | ||
| 358 | |||
| 359 | std::vector<std::string> split_query; | ||
| 360 | Common::SplitString(Common::StringFromFixedZeroTerminatedBuffer( | ||
| 361 | reinterpret_cast<const char*>(url->second.data()), url->second.size()), | ||
| 362 | '?', split_query); | ||
| 363 | |||
| 364 | // 2 -> Main URL '?' Query Parameters | ||
| 365 | // Less is missing info, More is malformed | ||
| 366 | if (split_query.size() != 2) { | ||
| 367 | LOG_ERROR(Service_AM, "EShop Arguments has more than one question mark, malformed"); | ||
| 368 | status = ResultCode(-1); | ||
| 369 | return; | ||
| 370 | } | ||
| 371 | |||
| 372 | std::vector<std::string> queries; | ||
| 373 | Common::SplitString(split_query[1], '&', queries); | ||
| 374 | |||
| 375 | const auto split_single_query = | ||
| 376 | [](const std::string& in) -> std::pair<std::string, std::string> { | ||
| 377 | const auto index = in.find('='); | ||
| 378 | if (index == std::string::npos || index == in.size() - 1) { | ||
| 379 | return {in, ""}; | ||
| 380 | } | ||
| 381 | |||
| 382 | return {in.substr(0, index), in.substr(index + 1)}; | ||
| 383 | }; | ||
| 384 | |||
| 385 | std::transform(queries.begin(), queries.end(), | ||
| 386 | std::inserter(shop_query, std::next(shop_query.begin())), split_single_query); | ||
| 387 | |||
| 388 | const auto scene = shop_query.find("scene"); | ||
| 389 | |||
| 390 | if (scene == shop_query.end()) { | ||
| 391 | LOG_ERROR(Service_AM, "No scene parameter was passed via shop query!"); | ||
| 392 | status = ResultCode(-1); | ||
| 393 | return; | ||
| 394 | } | ||
| 395 | |||
| 396 | const std::map<std::string, ShopWebTarget, std::less<>> target_map{ | ||
| 397 | {"product_detail", ShopWebTarget::ApplicationInfo}, | ||
| 398 | {"aocs", ShopWebTarget::AddOnContentList}, | ||
| 399 | {"subscriptions", ShopWebTarget::SubscriptionList}, | ||
| 400 | {"consumption", ShopWebTarget::ConsumableItemList}, | ||
| 401 | {"settings", ShopWebTarget::Settings}, | ||
| 402 | {"top", ShopWebTarget::Home}, | ||
| 403 | }; | ||
| 404 | |||
| 405 | const auto target = target_map.find(scene->second); | ||
| 406 | if (target == target_map.end()) { | ||
| 407 | LOG_ERROR(Service_AM, "Scene for shop query is invalid! (scene={})", scene->second); | ||
| 408 | status = ResultCode(-1); | ||
| 409 | return; | ||
| 410 | } | ||
| 411 | |||
| 412 | shop_web_target = target->second; | ||
| 413 | |||
| 414 | const auto title_id_data = shop_query.find("dst_app_id"); | ||
| 415 | if (title_id_data != shop_query.end()) { | ||
| 416 | title_id = std::stoull(title_id_data->second, nullptr, 0x10); | ||
| 417 | } | ||
| 418 | |||
| 419 | const auto mode_data = shop_query.find("mode"); | ||
| 420 | if (mode_data != shop_query.end()) { | ||
| 421 | shop_full_display = mode_data->second == "full"; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | void WebBrowser::InitializeOffline() { | ||
| 426 | if (args.find(WebArgTLVType::DocumentPath) == args.end() || | ||
| 427 | args.find(WebArgTLVType::DocumentKind) == args.end() || | ||
| 428 | args.find(WebArgTLVType::ApplicationID) == args.end()) { | ||
| 429 | status = ResultCode(-1); | ||
| 430 | LOG_ERROR(Service_AM, "Missing necessary parameters for initialization!"); | ||
| 431 | } | ||
| 432 | |||
| 433 | const auto url_data = args[WebArgTLVType::DocumentPath]; | ||
| 434 | filename = Common::StringFromFixedZeroTerminatedBuffer( | ||
| 435 | reinterpret_cast<const char*>(url_data.data()), url_data.size()); | ||
| 436 | |||
| 437 | OfflineWebSource source; | ||
| 438 | ASSERT(args[WebArgTLVType::DocumentKind].size() >= 4); | ||
| 439 | std::memcpy(&source, args[WebArgTLVType::DocumentKind].data(), sizeof(OfflineWebSource)); | ||
| 440 | |||
| 441 | constexpr std::array<const char*, 3> WEB_SOURCE_NAMES{ | ||
| 442 | "manual", | ||
| 443 | "legal", | ||
| 444 | "system", | ||
| 445 | }; | ||
| 446 | |||
| 447 | temporary_dir = | ||
| 448 | FileUtil::SanitizePath(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + "web_applet_" + | ||
| 449 | WEB_SOURCE_NAMES[static_cast<u32>(source) - 1], | ||
| 450 | FileUtil::DirectorySeparator::PlatformDefault); | ||
| 185 | FileUtil::DeleteDirRecursively(temporary_dir); | 451 | FileUtil::DeleteDirRecursively(temporary_dir); |
| 452 | |||
| 453 | u64 title_id = 0; // 0 corresponds to current process | ||
| 454 | ASSERT(args[WebArgTLVType::ApplicationID].size() >= 0x8); | ||
| 455 | std::memcpy(&title_id, args[WebArgTLVType::ApplicationID].data(), sizeof(u64)); | ||
| 456 | FileSys::ContentRecordType type = FileSys::ContentRecordType::Data; | ||
| 457 | |||
| 458 | switch (source) { | ||
| 459 | case OfflineWebSource::OfflineHtmlPage: | ||
| 460 | // While there is an AppID TLV field, in official SW this is always ignored. | ||
| 461 | title_id = 0; | ||
| 462 | type = FileSys::ContentRecordType::Manual; | ||
| 463 | break; | ||
| 464 | case OfflineWebSource::ApplicationLegalInformation: | ||
| 465 | type = FileSys::ContentRecordType::Legal; | ||
| 466 | break; | ||
| 467 | case OfflineWebSource::SystemDataPage: | ||
| 468 | type = FileSys::ContentRecordType::Data; | ||
| 469 | break; | ||
| 470 | } | ||
| 471 | |||
| 472 | if (title_id == 0) { | ||
| 473 | title_id = current_process_title_id; | ||
| 474 | } | ||
| 475 | |||
| 476 | offline_romfs = GetApplicationRomFS(title_id, type); | ||
| 477 | if (offline_romfs == nullptr) { | ||
| 478 | status = ResultCode(-1); | ||
| 479 | LOG_ERROR(Service_AM, "Failed to find offline data for request!"); | ||
| 480 | } | ||
| 481 | |||
| 482 | std::string path_additional_directory; | ||
| 483 | if (source == OfflineWebSource::OfflineHtmlPage) { | ||
| 484 | path_additional_directory = std::string(DIR_SEP).append("html-document"); | ||
| 485 | } | ||
| 486 | |||
| 487 | filename = | ||
| 488 | FileUtil::SanitizePath(temporary_dir + path_additional_directory + DIR_SEP + filename, | ||
| 489 | FileUtil::DirectorySeparator::PlatformDefault); | ||
| 490 | } | ||
| 491 | |||
| 492 | void WebBrowser::ExecuteShop() { | ||
| 493 | const auto callback = [this]() { Finalize(); }; | ||
| 494 | |||
| 495 | const auto check_optional_parameter = [this](const auto& p) { | ||
| 496 | if (!p.has_value()) { | ||
| 497 | LOG_ERROR(Service_AM, "Missing one or more necessary parameters for execution!"); | ||
| 498 | status = ResultCode(-1); | ||
| 499 | return false; | ||
| 500 | } | ||
| 501 | |||
| 502 | return true; | ||
| 503 | }; | ||
| 504 | |||
| 505 | switch (shop_web_target) { | ||
| 506 | case ShopWebTarget::ApplicationInfo: | ||
| 507 | if (!check_optional_parameter(title_id)) | ||
| 508 | return; | ||
| 509 | frontend_e_commerce->ShowApplicationInformation(callback, *title_id, user_id, | ||
| 510 | shop_full_display, shop_extra_parameter); | ||
| 511 | break; | ||
| 512 | case ShopWebTarget::AddOnContentList: | ||
| 513 | if (!check_optional_parameter(title_id)) | ||
| 514 | return; | ||
| 515 | frontend_e_commerce->ShowAddOnContentList(callback, *title_id, user_id, shop_full_display); | ||
| 516 | break; | ||
| 517 | case ShopWebTarget::ConsumableItemList: | ||
| 518 | if (!check_optional_parameter(title_id)) | ||
| 519 | return; | ||
| 520 | frontend_e_commerce->ShowConsumableItemList(callback, *title_id, user_id); | ||
| 521 | break; | ||
| 522 | case ShopWebTarget::Home: | ||
| 523 | if (!check_optional_parameter(user_id)) | ||
| 524 | return; | ||
| 525 | if (!check_optional_parameter(shop_full_display)) | ||
| 526 | return; | ||
| 527 | frontend_e_commerce->ShowShopHome(callback, *user_id, *shop_full_display); | ||
| 528 | break; | ||
| 529 | case ShopWebTarget::Settings: | ||
| 530 | if (!check_optional_parameter(user_id)) | ||
| 531 | return; | ||
| 532 | if (!check_optional_parameter(shop_full_display)) | ||
| 533 | return; | ||
| 534 | frontend_e_commerce->ShowSettings(callback, *user_id, *shop_full_display); | ||
| 535 | break; | ||
| 536 | case ShopWebTarget::SubscriptionList: | ||
| 537 | if (!check_optional_parameter(title_id)) | ||
| 538 | return; | ||
| 539 | frontend_e_commerce->ShowSubscriptionList(callback, *title_id, user_id); | ||
| 540 | break; | ||
| 541 | default: | ||
| 542 | UNREACHABLE(); | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 546 | void WebBrowser::ExecuteOffline() { | ||
| 547 | frontend.OpenPageLocal(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); | ||
| 186 | } | 548 | } |
| 187 | 549 | ||
| 188 | } // namespace Service::AM::Applets | 550 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index 7e0f34c7d..870f57b64 100644 --- a/src/core/hle/service/am/applets/web_browser.h +++ b/src/core/hle/service/am/applets/web_browser.h | |||
| @@ -4,15 +4,22 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <map> | ||
| 7 | #include "core/file_sys/vfs_types.h" | 8 | #include "core/file_sys/vfs_types.h" |
| 8 | #include "core/hle/service/am/am.h" | 9 | #include "core/hle/service/am/am.h" |
| 9 | #include "core/hle/service/am/applets/applets.h" | 10 | #include "core/hle/service/am/applets/applets.h" |
| 10 | 11 | ||
| 11 | namespace Service::AM::Applets { | 12 | namespace Service::AM::Applets { |
| 12 | 13 | ||
| 14 | enum class ShimKind : u32; | ||
| 15 | enum class ShopWebTarget; | ||
| 16 | enum class WebArgTLVType : u16; | ||
| 17 | |||
| 13 | class WebBrowser final : public Applet { | 18 | class WebBrowser final : public Applet { |
| 14 | public: | 19 | public: |
| 15 | WebBrowser(Core::Frontend::WebBrowserApplet& frontend); | 20 | WebBrowser(Core::Frontend::WebBrowserApplet& frontend, u64 current_process_title_id, |
| 21 | Core::Frontend::ECommerceApplet* frontend_e_commerce = nullptr); | ||
| 22 | |||
| 16 | ~WebBrowser() override; | 23 | ~WebBrowser() override; |
| 17 | 24 | ||
| 18 | void Initialize() override; | 25 | void Initialize() override; |
| @@ -32,15 +39,41 @@ public: | |||
| 32 | void Finalize(); | 39 | void Finalize(); |
| 33 | 40 | ||
| 34 | private: | 41 | private: |
| 42 | void InitializeInternal(); | ||
| 43 | void ExecuteInternal(); | ||
| 44 | |||
| 45 | // Specific initializers for the types of web applets | ||
| 46 | void InitializeShop(); | ||
| 47 | void InitializeOffline(); | ||
| 48 | |||
| 49 | // Specific executors for the types of web applets | ||
| 50 | void ExecuteShop(); | ||
| 51 | void ExecuteOffline(); | ||
| 52 | |||
| 35 | Core::Frontend::WebBrowserApplet& frontend; | 53 | Core::Frontend::WebBrowserApplet& frontend; |
| 36 | 54 | ||
| 55 | // Extra frontends for specialized functions | ||
| 56 | Core::Frontend::ECommerceApplet* frontend_e_commerce; | ||
| 57 | |||
| 37 | bool complete = false; | 58 | bool complete = false; |
| 38 | bool unpacked = false; | 59 | bool unpacked = false; |
| 39 | ResultCode status = RESULT_SUCCESS; | 60 | ResultCode status = RESULT_SUCCESS; |
| 40 | 61 | ||
| 41 | FileSys::VirtualFile manual_romfs; | 62 | u64 current_process_title_id; |
| 63 | |||
| 64 | ShimKind kind; | ||
| 65 | std::map<WebArgTLVType, std::vector<u8>> args; | ||
| 66 | |||
| 67 | FileSys::VirtualFile offline_romfs; | ||
| 42 | std::string temporary_dir; | 68 | std::string temporary_dir; |
| 43 | std::string filename; | 69 | std::string filename; |
| 70 | |||
| 71 | ShopWebTarget shop_web_target; | ||
| 72 | std::map<std::string, std::string, std::less<>> shop_query; | ||
| 73 | std::optional<u64> title_id = 0; | ||
| 74 | std::optional<u128> user_id; | ||
| 75 | std::optional<bool> shop_full_display; | ||
| 76 | std::string shop_extra_parameter; | ||
| 44 | }; | 77 | }; |
| 45 | 78 | ||
| 46 | } // namespace Service::AM::Applets | 79 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index beae9c510..ec9d755b7 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -204,7 +204,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | |||
| 204 | SM::ServiceManager::InstallInterfaces(sm); | 204 | SM::ServiceManager::InstallInterfaces(sm); |
| 205 | 205 | ||
| 206 | Account::InstallInterfaces(system); | 206 | Account::InstallInterfaces(system); |
| 207 | AM::InstallInterfaces(*sm, nv_flinger); | 207 | AM::InstallInterfaces(*sm, nv_flinger, system); |
| 208 | AOC::InstallInterfaces(*sm); | 208 | AOC::InstallInterfaces(*sm); |
| 209 | APM::InstallInterfaces(*sm); | 209 | APM::InstallInterfaces(*sm); |
| 210 | Audio::InstallInterfaces(*sm); | 210 | Audio::InstallInterfaces(*sm); |
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp index ac80b2fa2..33f1c385d 100644 --- a/src/yuzu/applets/web_browser.cpp +++ b/src/yuzu/applets/web_browser.cpp | |||
| @@ -87,8 +87,8 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { | |||
| 87 | 87 | ||
| 88 | QtWebBrowser::~QtWebBrowser() = default; | 88 | QtWebBrowser::~QtWebBrowser() = default; |
| 89 | 89 | ||
| 90 | void QtWebBrowser::OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback, | 90 | void QtWebBrowser::OpenPageLocal(std::string_view url, std::function<void()> unpack_romfs_callback, |
| 91 | std::function<void()> finished_callback) { | 91 | std::function<void()> finished_callback) { |
| 92 | this->unpack_romfs_callback = std::move(unpack_romfs_callback); | 92 | this->unpack_romfs_callback = std::move(unpack_romfs_callback); |
| 93 | this->finished_callback = std::move(finished_callback); | 93 | this->finished_callback = std::move(finished_callback); |
| 94 | 94 | ||
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h index 1a3d67353..b38437e46 100644 --- a/src/yuzu/applets/web_browser.h +++ b/src/yuzu/applets/web_browser.h | |||
| @@ -37,8 +37,8 @@ public: | |||
| 37 | explicit QtWebBrowser(GMainWindow& main_window); | 37 | explicit QtWebBrowser(GMainWindow& main_window); |
| 38 | ~QtWebBrowser() override; | 38 | ~QtWebBrowser() override; |
| 39 | 39 | ||
| 40 | void OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback, | 40 | void OpenPageLocal(std::string_view url, std::function<void()> unpack_romfs_callback, |
| 41 | std::function<void()> finished_callback) override; | 41 | std::function<void()> finished_callback) override; |
| 42 | 42 | ||
| 43 | signals: | 43 | signals: |
| 44 | void MainWindowOpenPage(std::string_view filename, std::string_view additional_args) const; | 44 | void MainWindowOpenPage(std::string_view filename, std::string_view additional_args) const; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 66a7080c9..47e46f574 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -814,11 +814,13 @@ bool GMainWindow::LoadROM(const QString& filename) { | |||
| 814 | system.SetGPUDebugContext(debug_context); | 814 | system.SetGPUDebugContext(debug_context); |
| 815 | 815 | ||
| 816 | system.SetAppletFrontendSet({ | 816 | system.SetAppletFrontendSet({ |
| 817 | std::make_unique<QtErrorDisplay>(*this), | 817 | nullptr, // Parental Controls |
| 818 | nullptr, | 818 | std::make_unique<QtErrorDisplay>(*this), // |
| 819 | std::make_unique<QtProfileSelector>(*this), | 819 | nullptr, // Photo Viewer |
| 820 | std::make_unique<QtSoftwareKeyboard>(*this), | 820 | std::make_unique<QtProfileSelector>(*this), // |
| 821 | std::make_unique<QtWebBrowser>(*this), | 821 | std::make_unique<QtSoftwareKeyboard>(*this), // |
| 822 | std::make_unique<QtWebBrowser>(*this), // | ||
| 823 | nullptr, // E-Commerce | ||
| 822 | }); | 824 | }); |
| 823 | 825 | ||
| 824 | const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; | 826 | const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; |