applets/web: Initial implementation of the web browser applet
This commit is contained in:
		| @@ -2,8 +2,11 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <optional> | ||||||
|  |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/frontend/applets/web_browser.h" | #include "core/frontend/applets/web_browser.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| @@ -12,6 +15,76 @@ | |||||||
|  |  | ||||||
| namespace Service::AM::Applets { | namespace Service::AM::Applets { | ||||||
|  |  | ||||||
|  | namespace { | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | void ParseRawValue(T& value, const std::vector<u8>& data) { | ||||||
|  |     static_assert(std::is_trivially_copyable_v<T>, | ||||||
|  |                   "It's undefined behavior to use memcpy with non-trivially copyable objects"); | ||||||
|  |     std::memcpy(&value, data.data(), data.size()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | T ParseRawValue(const std::vector<u8>& data) { | ||||||
|  |     T value; | ||||||
|  |     ParseRawValue(value, data); | ||||||
|  |     return value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string ParseStringValue(const std::vector<u8>& data) { | ||||||
|  |     return Common::StringFromFixedZeroTerminatedBuffer(reinterpret_cast<const char*>(data.data()), | ||||||
|  |                                                        data.size()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | WebArgInputTLVMap ReadWebArgs(const std::vector<u8>& web_arg, WebArgHeader& web_arg_header) { | ||||||
|  |     std::memcpy(&web_arg_header, web_arg.data(), sizeof(WebArgHeader)); | ||||||
|  |  | ||||||
|  |     if (web_arg.size() == sizeof(WebArgHeader)) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     WebArgInputTLVMap input_tlv_map; | ||||||
|  |  | ||||||
|  |     u64 current_offset = sizeof(WebArgHeader); | ||||||
|  |  | ||||||
|  |     for (std::size_t i = 0; i < web_arg_header.total_tlv_entries; ++i) { | ||||||
|  |         if (web_arg.size() < current_offset + sizeof(WebArgInputTLV)) { | ||||||
|  |             return input_tlv_map; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         WebArgInputTLV input_tlv; | ||||||
|  |         std::memcpy(&input_tlv, web_arg.data() + current_offset, sizeof(WebArgInputTLV)); | ||||||
|  |  | ||||||
|  |         current_offset += sizeof(WebArgInputTLV); | ||||||
|  |  | ||||||
|  |         if (web_arg.size() < current_offset + input_tlv.arg_data_size) { | ||||||
|  |             return input_tlv_map; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         std::vector<u8> data(input_tlv.arg_data_size); | ||||||
|  |         std::memcpy(data.data(), web_arg.data() + current_offset, input_tlv.arg_data_size); | ||||||
|  |  | ||||||
|  |         current_offset += input_tlv.arg_data_size; | ||||||
|  |  | ||||||
|  |         input_tlv_map.insert_or_assign(input_tlv.input_tlv_type, std::move(data)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return input_tlv_map; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::optional<std::vector<u8>> GetInputTLVData(const WebArgInputTLVMap& input_tlv_map, | ||||||
|  |                                                WebArgInputTLVType input_tlv_type) { | ||||||
|  |     const auto map_it = input_tlv_map.find(input_tlv_type); | ||||||
|  |  | ||||||
|  |     if (map_it == input_tlv_map.end()) { | ||||||
|  |         return std::nullopt; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return map_it->second; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
| WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) | WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) | ||||||
|     : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} |     : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} | ||||||
|  |  | ||||||
| @@ -19,6 +92,55 @@ WebBrowser::~WebBrowser() = default; | |||||||
|  |  | ||||||
| void WebBrowser::Initialize() { | void WebBrowser::Initialize() { | ||||||
|     Applet::Initialize(); |     Applet::Initialize(); | ||||||
|  |  | ||||||
|  |     LOG_INFO(Service_AM, "Initializing Web Browser Applet."); | ||||||
|  |  | ||||||
|  |     LOG_DEBUG(Service_AM, | ||||||
|  |               "Initializing Applet with common_args: arg_version={}, lib_version={}, " | ||||||
|  |               "play_startup_sound={}, size={}, system_tick={}, theme_color={}", | ||||||
|  |               common_args.arguments_version, common_args.library_version, | ||||||
|  |               common_args.play_startup_sound, common_args.size, common_args.system_tick, | ||||||
|  |               common_args.theme_color); | ||||||
|  |  | ||||||
|  |     web_applet_version = WebAppletVersion{common_args.library_version}; | ||||||
|  |  | ||||||
|  |     const auto web_arg_storage = broker.PopNormalDataToApplet(); | ||||||
|  |     ASSERT(web_arg_storage != nullptr); | ||||||
|  |  | ||||||
|  |     const auto& web_arg = web_arg_storage->GetData(); | ||||||
|  |     ASSERT_OR_EXECUTE(web_arg.size() >= sizeof(WebArgHeader), { return; }); | ||||||
|  |  | ||||||
|  |     web_arg_input_tlv_map = ReadWebArgs(web_arg, web_arg_header); | ||||||
|  |  | ||||||
|  |     LOG_DEBUG(Service_AM, "WebArgHeader: total_tlv_entries={}, shim_kind={}", | ||||||
|  |               web_arg_header.total_tlv_entries, web_arg_header.shim_kind); | ||||||
|  |  | ||||||
|  |     switch (web_arg_header.shim_kind) { | ||||||
|  |     case ShimKind::Shop: | ||||||
|  |         InitializeShop(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Login: | ||||||
|  |         InitializeLogin(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Offline: | ||||||
|  |         InitializeOffline(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Share: | ||||||
|  |         InitializeShare(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Web: | ||||||
|  |         InitializeWeb(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Wifi: | ||||||
|  |         InitializeWifi(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Lobby: | ||||||
|  |         InitializeLobby(); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         UNREACHABLE_MSG("Invalid ShimKind={}", web_arg_header.shim_kind); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool WebBrowser::TransactionComplete() const { | bool WebBrowser::TransactionComplete() const { | ||||||
| @@ -30,9 +152,110 @@ ResultCode WebBrowser::GetStatus() const { | |||||||
| } | } | ||||||
|  |  | ||||||
| void WebBrowser::ExecuteInteractive() { | void WebBrowser::ExecuteInteractive() { | ||||||
|     UNIMPLEMENTED_MSG("Unexpected interactive data recieved!"); |     UNIMPLEMENTED_MSG("WebSession is not implemented"); | ||||||
| } | } | ||||||
|  |  | ||||||
| void WebBrowser::Execute() {} | void WebBrowser::Execute() { | ||||||
|  |     switch (web_arg_header.shim_kind) { | ||||||
|  |     case ShimKind::Shop: | ||||||
|  |         ExecuteShop(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Login: | ||||||
|  |         ExecuteLogin(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Offline: | ||||||
|  |         ExecuteOffline(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Share: | ||||||
|  |         ExecuteShare(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Web: | ||||||
|  |         ExecuteWeb(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Wifi: | ||||||
|  |         ExecuteWifi(); | ||||||
|  |         break; | ||||||
|  |     case ShimKind::Lobby: | ||||||
|  |         ExecuteLobby(); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         UNREACHABLE_MSG("Invalid ShimKind={}", web_arg_header.shim_kind); | ||||||
|  |         WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) { | ||||||
|  |     if ((web_arg_header.shim_kind == ShimKind::Share && | ||||||
|  |          web_applet_version >= WebAppletVersion::Version196608) || | ||||||
|  |         (web_arg_header.shim_kind == ShimKind::Web && | ||||||
|  |          web_applet_version >= WebAppletVersion::Version524288)) { | ||||||
|  |         // TODO: Push Output TLVs instead of a WebCommonReturnValue | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     WebCommonReturnValue web_common_return_value; | ||||||
|  |  | ||||||
|  |     web_common_return_value.exit_reason = exit_reason; | ||||||
|  |     std::memcpy(&web_common_return_value.last_url, last_url.data(), last_url.size()); | ||||||
|  |     web_common_return_value.last_url_size = last_url.size(); | ||||||
|  |  | ||||||
|  |     LOG_DEBUG(Service_AM, "WebCommonReturnValue: exit_reason={}, last_url={}, last_url_size={}", | ||||||
|  |               exit_reason, last_url, last_url.size()); | ||||||
|  |  | ||||||
|  |     complete = true; | ||||||
|  |     std::vector<u8> out_data(sizeof(WebCommonReturnValue)); | ||||||
|  |     std::memcpy(out_data.data(), &web_common_return_value, out_data.size()); | ||||||
|  |     broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | ||||||
|  |     broker.SignalStateChanged(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeShop() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeLogin() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeOffline() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeShare() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeWeb() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeWifi() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::InitializeLobby() {} | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteShop() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Shop Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteLogin() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Login Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteOffline() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Offline Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteShare() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Share Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteWeb() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Web Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteWifi() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Wifi Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WebBrowser::ExecuteLobby() { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, Lobby Applet is not implemented"); | ||||||
|  |     WebBrowserExit(WebExitReason::EndButtonPressed); | ||||||
|  | } | ||||||
|  |  | ||||||
| } // namespace Service::AM::Applets | } // namespace Service::AM::Applets | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_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" | ||||||
|  |  | ||||||
| namespace Core { | namespace Core { | ||||||
| class System; | class System; | ||||||
| @@ -28,12 +29,36 @@ public: | |||||||
|     void ExecuteInteractive() override; |     void ExecuteInteractive() override; | ||||||
|     void Execute() override; |     void Execute() override; | ||||||
|  |  | ||||||
|  |     void WebBrowserExit(WebExitReason exit_reason, std::string last_url = ""); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     // Initializers for the various types of browser applets | ||||||
|  |     void InitializeShop(); | ||||||
|  |     void InitializeLogin(); | ||||||
|  |     void InitializeOffline(); | ||||||
|  |     void InitializeShare(); | ||||||
|  |     void InitializeWeb(); | ||||||
|  |     void InitializeWifi(); | ||||||
|  |     void InitializeLobby(); | ||||||
|  |  | ||||||
|  |     // Executors for the various types of browser applets | ||||||
|  |     void ExecuteShop(); | ||||||
|  |     void ExecuteLogin(); | ||||||
|  |     void ExecuteOffline(); | ||||||
|  |     void ExecuteShare(); | ||||||
|  |     void ExecuteWeb(); | ||||||
|  |     void ExecuteWifi(); | ||||||
|  |     void ExecuteLobby(); | ||||||
|  |  | ||||||
|     const Core::Frontend::WebBrowserApplet& frontend; |     const Core::Frontend::WebBrowserApplet& frontend; | ||||||
|  |  | ||||||
|     bool complete{false}; |     bool complete{false}; | ||||||
|     ResultCode status{RESULT_SUCCESS}; |     ResultCode status{RESULT_SUCCESS}; | ||||||
|  |  | ||||||
|  |     WebAppletVersion web_applet_version; | ||||||
|  |     WebArgHeader web_arg_header; | ||||||
|  |     WebArgInputTLVMap web_arg_input_tlv_map; | ||||||
|  |  | ||||||
|     Core::System& system; |     Core::System& system; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										178
									
								
								src/core/hle/service/am/applets/web_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/core/hle/service/am/applets/web_types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | |||||||
|  | // Copyright 2020 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <array> | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #include "common/common_funcs.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/swap.h" | ||||||
|  |  | ||||||
|  | namespace Service::AM::Applets { | ||||||
|  |  | ||||||
|  | enum class WebAppletVersion : u32_le { | ||||||
|  |     Version0 = 0x0,          // Only used by WifiWebAuthApplet | ||||||
|  |     Version131072 = 0x20000, // 1.0.0 - 2.3.0 | ||||||
|  |     Version196608 = 0x30000, // 3.0.0 - 4.1.0 | ||||||
|  |     Version327680 = 0x50000, // 5.0.0 - 5.1.0 | ||||||
|  |     Version393216 = 0x60000, // 6.0.0 - 7.0.1 | ||||||
|  |     Version524288 = 0x80000, // 8.0.0+ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class ShimKind : u32 { | ||||||
|  |     Shop = 1, | ||||||
|  |     Login = 2, | ||||||
|  |     Offline = 3, | ||||||
|  |     Share = 4, | ||||||
|  |     Web = 5, | ||||||
|  |     Wifi = 6, | ||||||
|  |     Lobby = 7, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class WebExitReason : u32 { | ||||||
|  |     EndButtonPressed = 0, | ||||||
|  |     BackButtonPressed = 1, | ||||||
|  |     ExitRequested = 2, | ||||||
|  |     CallbackURL = 3, | ||||||
|  |     WindowClosed = 4, | ||||||
|  |     ErrorDialog = 7, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class WebArgInputTLVType : u16 { | ||||||
|  |     InitialURL = 0x1, | ||||||
|  |     CallbackURL = 0x3, | ||||||
|  |     CallbackableURL = 0x4, | ||||||
|  |     ApplicationID = 0x5, | ||||||
|  |     DocumentPath = 0x6, | ||||||
|  |     DocumentKind = 0x7, | ||||||
|  |     SystemDataID = 0x8, | ||||||
|  |     ShareStartPage = 0x9, | ||||||
|  |     Whitelist = 0xA, | ||||||
|  |     News = 0xB, | ||||||
|  |     UserID = 0xE, | ||||||
|  |     AlbumEntry0 = 0xF, | ||||||
|  |     ScreenShotEnabled = 0x10, | ||||||
|  |     EcClientCertEnabled = 0x11, | ||||||
|  |     PlayReportEnabled = 0x13, | ||||||
|  |     BootDisplayKind = 0x17, | ||||||
|  |     BackgroundKind = 0x18, | ||||||
|  |     FooterEnabled = 0x19, | ||||||
|  |     PointerEnabled = 0x1A, | ||||||
|  |     LeftStickMode = 0x1B, | ||||||
|  |     KeyRepeatFrame1 = 0x1C, | ||||||
|  |     KeyRepeatFrame2 = 0x1D, | ||||||
|  |     BootAsMediaPlayerInverted = 0x1E, | ||||||
|  |     DisplayURLKind = 0x1F, | ||||||
|  |     BootAsMediaPlayer = 0x21, | ||||||
|  |     ShopJumpEnabled = 0x22, | ||||||
|  |     MediaAutoPlayEnabled = 0x23, | ||||||
|  |     LobbyParameter = 0x24, | ||||||
|  |     ApplicationAlbumEntry = 0x26, | ||||||
|  |     JsExtensionEnabled = 0x27, | ||||||
|  |     AdditionalCommentText = 0x28, | ||||||
|  |     TouchEnabledOnContents = 0x29, | ||||||
|  |     UserAgentAdditionalString = 0x2A, | ||||||
|  |     AdditionalMediaData0 = 0x2B, | ||||||
|  |     MediaPlayerAutoCloseEnabled = 0x2C, | ||||||
|  |     PageCacheEnabled = 0x2D, | ||||||
|  |     WebAudioEnabled = 0x2E, | ||||||
|  |     YouTubeVideoWhitelist = 0x31, | ||||||
|  |     FooterFixedKind = 0x32, | ||||||
|  |     PageFadeEnabled = 0x33, | ||||||
|  |     MediaCreatorApplicationRatingAge = 0x34, | ||||||
|  |     BootLoadingIconEnabled = 0x35, | ||||||
|  |     PageScrollIndicatorEnabled = 0x36, | ||||||
|  |     MediaPlayerSpeedControlEnabled = 0x37, | ||||||
|  |     AlbumEntry1 = 0x38, | ||||||
|  |     AlbumEntry2 = 0x39, | ||||||
|  |     AlbumEntry3 = 0x3A, | ||||||
|  |     AdditionalMediaData1 = 0x3B, | ||||||
|  |     AdditionalMediaData2 = 0x3C, | ||||||
|  |     AdditionalMediaData3 = 0x3D, | ||||||
|  |     BootFooterButton = 0x3E, | ||||||
|  |     OverrideWebAudioVolume = 0x3F, | ||||||
|  |     OverrideMediaAudioVolume = 0x40, | ||||||
|  |     BootMode = 0x41, | ||||||
|  |     WebSessionEnabled = 0x42, | ||||||
|  |     MediaPlayerOfflineEnabled = 0x43, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class WebArgOutputTLVType : u16 { | ||||||
|  |     ShareExitReason = 0x1, | ||||||
|  |     LastURL = 0x2, | ||||||
|  |     LastURLSize = 0x3, | ||||||
|  |     SharePostResult = 0x4, | ||||||
|  |     PostServiceName = 0x5, | ||||||
|  |     PostServiceNameSize = 0x6, | ||||||
|  |     PostID = 0x7, | ||||||
|  |     PostIDSize = 0x8, | ||||||
|  |     MediaPlayerAutoClosedByCompletion = 0x9, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class DocumentKind : u32 { | ||||||
|  |     OfflineHtmlPage = 1, | ||||||
|  |     ApplicationLegalInformation = 2, | ||||||
|  |     SystemDataPage = 3, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class ShareStartPage : u32 { | ||||||
|  |     Default, | ||||||
|  |     Settings, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class BootDisplayKind : u32 { | ||||||
|  |     Default, | ||||||
|  |     White, | ||||||
|  |     Black, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class BackgroundKind : u32 { | ||||||
|  |     Default, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class LeftStickMode : u32 { | ||||||
|  |     Pointer, | ||||||
|  |     Cursor, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum class WebSessionBootMode : u32 { | ||||||
|  |     AllForeground, | ||||||
|  |     AllForegroundInitiallyHidden, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct WebArgHeader { | ||||||
|  |     u16 total_tlv_entries{}; | ||||||
|  |     INSERT_PADDING_BYTES(2); | ||||||
|  |     ShimKind shim_kind{}; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(WebArgHeader) == 0x8, "WebArgHeader has incorrect size."); | ||||||
|  |  | ||||||
|  | struct WebArgInputTLV { | ||||||
|  |     WebArgInputTLVType input_tlv_type{}; | ||||||
|  |     u16 arg_data_size{}; | ||||||
|  |     INSERT_PADDING_WORDS(1); | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(WebArgInputTLV) == 0x8, "WebArgInputTLV has incorrect size."); | ||||||
|  |  | ||||||
|  | struct WebArgOutputTLV { | ||||||
|  |     WebArgOutputTLVType output_tlv_type{}; | ||||||
|  |     u16 arg_data_size{}; | ||||||
|  |     INSERT_PADDING_WORDS(1); | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(WebArgOutputTLV) == 0x8, "WebArgOutputTLV has incorrect size."); | ||||||
|  |  | ||||||
|  | struct WebCommonReturnValue { | ||||||
|  |     WebExitReason exit_reason{}; | ||||||
|  |     INSERT_PADDING_WORDS(1); | ||||||
|  |     std::array<char, 0x1000> last_url{}; | ||||||
|  |     u64 last_url_size{}; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(WebCommonReturnValue) == 0x1010, "WebCommonReturnValue has incorrect size."); | ||||||
|  |  | ||||||
|  | using WebArgInputTLVMap = std::unordered_map<WebArgInputTLVType, std::vector<u8>>; | ||||||
|  |  | ||||||
|  | } // namespace Service::AM::Applets | ||||||
		Reference in New Issue
	
	Block a user