mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	web_browser: Correct structures and properly parse TLVs/ShimKind
Much, much more HW-accurate and allows us to easily support all of the different web 'shim' types.
This commit is contained in:
		
							parent
							
								
									b889167b2c
								
							
						
					
					
						commit
						675aa5f719
					
				| @ -19,7 +19,9 @@ | ||||
| #include "core/file_sys/nca_metadata.h" | ||||
| #include "core/file_sys/registered_cache.h" | ||||
| #include "core/file_sys/romfs.h" | ||||
| #include "core/file_sys/system_archive/system_archive.h" | ||||
| #include "core/file_sys/vfs_types.h" | ||||
| #include "core/frontend/applets/general_frontend.h" | ||||
| #include "core/frontend/applets/web_browser.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/service/am/applets/web_browser.h" | ||||
| @ -28,74 +30,186 @@ | ||||
| 
 | ||||
| namespace Service::AM::Applets { | ||||
| 
 | ||||
| // TODO(DarkLordZach): There are other arguments in the WebBuffer structure that are currently not
 | ||||
| // parsed, for example footer mode and left stick mode. Some of these are not particularly relevant,
 | ||||
| // but some may be worth an implementation.
 | ||||
| constexpr u16 WEB_ARGUMENT_URL_TYPE = 0x6; | ||||
| 
 | ||||
| struct WebBufferHeader { | ||||
|     u16 count; | ||||
|     INSERT_PADDING_BYTES(6); | ||||
| enum class WebArgTLVType : u16 { | ||||
|     InitialURL = 0x1, | ||||
|     ShopArgumentsURL = 0x2, ///< TODO(DarkLordZach): This is not the official name.
 | ||||
|     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, | ||||
|     Unk12 = 0x12, | ||||
|     PlayReportEnabled = 0x13, | ||||
|     Unk14 = 0x14, | ||||
|     Unk15 = 0x15, | ||||
|     BootDisplayKind = 0x17, | ||||
|     BackgroundKind = 0x18, | ||||
|     FooterEnabled = 0x19, | ||||
|     PointerEnabled = 0x1A, | ||||
|     LeftStickMode = 0x1B, | ||||
|     KeyRepeatFrame1 = 0x1C, | ||||
|     KeyRepeatFrame2 = 0x1D, | ||||
|     BootAsMediaPlayerInv = 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, | ||||
|     Unk2F = 0x2F, | ||||
|     YouTubeVideoWhitelist = 0x31, | ||||
|     FooterFixedKind = 0x32, | ||||
|     PageFadeEnabled = 0x33, | ||||
|     MediaCreatorApplicationRatingAge = 0x34, | ||||
|     BootLoadingIconEnabled = 0x35, | ||||
|     PageScrollIndicationEnabled = 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, | ||||
| }; | ||||
| static_assert(sizeof(WebBufferHeader) == 0x8, "WebBufferHeader has incorrect size."); | ||||
| 
 | ||||
| struct WebArgumentHeader { | ||||
|     u16 type; | ||||
| enum class ShimKind : u32 { | ||||
|     Shop = 1, | ||||
|     Login = 2, | ||||
|     Offline = 3, | ||||
|     Share = 4, | ||||
|     Web = 5, | ||||
|     Wifi = 6, | ||||
|     Lobby = 7, | ||||
| }; | ||||
| 
 | ||||
| constexpr std::size_t SHIM_KIND_COUNT = 0x8; | ||||
| 
 | ||||
| struct WebArgHeader { | ||||
|     u16 count; | ||||
|     INSERT_PADDING_BYTES(2); | ||||
|     ShimKind kind; | ||||
| }; | ||||
| static_assert(sizeof(WebArgHeader) == 0x8, "WebArgHeader has incorrect size."); | ||||
| 
 | ||||
| struct WebArgTLV { | ||||
|     WebArgTLVType type; | ||||
|     u16 size; | ||||
|     u32 offset; | ||||
| }; | ||||
| static_assert(sizeof(WebArgumentHeader) == 0x8, "WebArgumentHeader has incorrect size."); | ||||
| static_assert(sizeof(WebArgTLV) == 0x8, "WebArgTLV has incorrect size."); | ||||
| 
 | ||||
| struct WebArgumentResult { | ||||
| struct WebCommonReturnValue { | ||||
|     u32 result_code; | ||||
|     INSERT_PADDING_BYTES(0x4); | ||||
|     std::array<char, 0x1000> last_url; | ||||
|     u64 last_url_size; | ||||
| }; | ||||
| static_assert(sizeof(WebArgumentResult) == 0x1010, "WebArgumentResult has incorrect size."); | ||||
| static_assert(sizeof(WebCommonReturnValue) == 0x1010, "WebCommonReturnValue has incorrect size."); | ||||
| 
 | ||||
| static std::vector<u8> GetArgumentDataForTagType(const std::vector<u8>& data, u16 type) { | ||||
|     WebBufferHeader header; | ||||
|     ASSERT(sizeof(WebBufferHeader) <= data.size()); | ||||
|     std::memcpy(&header, data.data(), sizeof(WebBufferHeader)); | ||||
| struct WebWifiPageArg { | ||||
|     INSERT_PADDING_BYTES(4); | ||||
|     std::array<char, 0x100> connection_test_url; | ||||
|     std::array<char, 0x400> initial_url; | ||||
|     std::array<u8, 0x10> nifm_network_uuid; | ||||
|     u32 nifm_requirement; | ||||
| }; | ||||
| static_assert(sizeof(WebWifiPageArg) == 0x518, "WebWifiPageArg has incorrect size."); | ||||
| 
 | ||||
|     u64 offset = sizeof(WebBufferHeader); | ||||
|     for (u16 i = 0; i < header.count; ++i) { | ||||
|         WebArgumentHeader arg; | ||||
|         ASSERT(offset + sizeof(WebArgumentHeader) <= data.size()); | ||||
|         std::memcpy(&arg, data.data() + offset, sizeof(WebArgumentHeader)); | ||||
|         offset += sizeof(WebArgumentHeader); | ||||
| struct WebWifiReturnValue { | ||||
|     INSERT_PADDING_BYTES(4); | ||||
|     u32 result; | ||||
| }; | ||||
| static_assert(sizeof(WebWifiReturnValue) == 0x8, "WebWifiReturnValue has incorrect size."); | ||||
| 
 | ||||
|         if (arg.type == type) { | ||||
|             std::vector<u8> out(arg.size); | ||||
|             offset += arg.offset; | ||||
|             ASSERT(offset + arg.size <= data.size()); | ||||
|             std::memcpy(out.data(), data.data() + offset, out.size()); | ||||
| enum class OfflineWebSource : u32 { | ||||
|     OfflineHtmlPage = 0x1, | ||||
|     ApplicationLegalInformation = 0x2, | ||||
|     SystemDataPage = 0x3, | ||||
| }; | ||||
| 
 | ||||
| enum class ShopWebTarget { | ||||
|     ApplicationInfo, | ||||
|     AddOnContentList, | ||||
|     SubscriptionList, | ||||
|     ConsumableItemList, | ||||
|     Home, | ||||
|     Settings, | ||||
| }; | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| std::map<WebArgTLVType, std::vector<u8>> GetWebArguments(const std::vector<u8>& arg) { | ||||
|     WebArgHeader header{}; | ||||
|     if (arg.size() < sizeof(WebArgHeader)) | ||||
|         return {}; | ||||
| 
 | ||||
|     std::memcpy(&header, arg.data(), sizeof(WebArgHeader)); | ||||
| 
 | ||||
|     std::map<WebArgTLVType, std::vector<u8>> out; | ||||
|     u64 offset = sizeof(WebArgHeader); | ||||
|     for (std::size_t i = 0; i < header.count; ++i) { | ||||
|         WebArgTLV tlv{}; | ||||
|         if (arg.size() < (offset + sizeof(WebArgTLV))) | ||||
|             return out; | ||||
|         } | ||||
| 
 | ||||
|         offset += arg.offset + arg.size; | ||||
|         std::memcpy(&tlv, arg.data() + offset, sizeof(WebArgTLV)); | ||||
|         offset += sizeof(WebArgTLV); | ||||
| 
 | ||||
|         offset += tlv.offset; | ||||
|         if (arg.size() < (offset + tlv.size)) | ||||
|             return out; | ||||
| 
 | ||||
|         std::vector<u8> data(tlv.size); | ||||
|         std::memcpy(data.data(), arg.data() + offset, tlv.size); | ||||
|         offset += tlv.size; | ||||
| 
 | ||||
|         out.insert_or_assign(tlv.type, data); | ||||
|     } | ||||
| 
 | ||||
|     return {}; | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| static FileSys::VirtualFile GetManualRomFS() { | ||||
|     auto& loader{Core::System::GetInstance().GetAppLoader()}; | ||||
| 
 | ||||
|     FileSys::VirtualFile out; | ||||
|     if (loader.ReadManualRomFS(out) == Loader::ResultStatus::Success) | ||||
|         return out; | ||||
| 
 | ||||
| FileSys::VirtualFile GetApplicationRomFS(u64 title_id, FileSys::ContentRecordType type) { | ||||
|     const auto& installed{Core::System::GetInstance().GetContentProvider()}; | ||||
|     const auto res = installed.GetEntry(Core::System::GetInstance().CurrentProcess()->GetTitleID(), | ||||
|                                         FileSys::ContentRecordType::Manual); | ||||
|     const auto res = installed.GetEntry(title_id, type); | ||||
| 
 | ||||
|     if (res != nullptr) | ||||
|     if (res != nullptr) { | ||||
|         return res->GetRomFS(); | ||||
|     } | ||||
| 
 | ||||
|     if (type == FileSys::ContentRecordType::Data) { | ||||
|         return FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | ||||
|     } | ||||
| 
 | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend, | ||||
|                        Core::Frontend::ECommerceApplet* frontend_e_commerce) | ||||
|     : frontend(frontend), frontend_e_commerce(frontend_e_commerce) {} | ||||
| 
 | ||||
| WebBrowser::~WebBrowser() = default; | ||||
| 
 | ||||
| @ -111,24 +225,12 @@ void WebBrowser::Initialize() { | ||||
|     ASSERT(web_arg_storage != nullptr); | ||||
|     const auto& web_arg = web_arg_storage->GetData(); | ||||
| 
 | ||||
|     const auto url_data = GetArgumentDataForTagType(web_arg, WEB_ARGUMENT_URL_TYPE); | ||||
|     filename = Common::StringFromFixedZeroTerminatedBuffer( | ||||
|         reinterpret_cast<const char*>(url_data.data()), url_data.size()); | ||||
|     ASSERT(web_arg.size() >= 0x8); | ||||
|     std::memcpy(&kind, web_arg.data() + 0x4, sizeof(ShimKind)); | ||||
| 
 | ||||
|     temporary_dir = FileUtil::SanitizePath(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + | ||||
|                                                "web_applet_manual", | ||||
|                                            FileUtil::DirectorySeparator::PlatformDefault); | ||||
|     FileUtil::DeleteDirRecursively(temporary_dir); | ||||
|     args = GetWebArguments(web_arg); | ||||
| 
 | ||||
|     manual_romfs = GetManualRomFS(); | ||||
|     if (manual_romfs == nullptr) { | ||||
|         status = ResultCode(-1); | ||||
|         LOG_ERROR(Service_AM, "Failed to find manual for current process!"); | ||||
|     } | ||||
| 
 | ||||
|     filename = | ||||
|         FileUtil::SanitizePath(temporary_dir + DIR_SEP + "html-document" + DIR_SEP + filename, | ||||
|                                FileUtil::DirectorySeparator::PlatformDefault); | ||||
|     InitializeInternal(); | ||||
| } | ||||
| 
 | ||||
| bool WebBrowser::TransactionComplete() const { | ||||
|  | ||||
| @ -10,6 +10,9 @@ | ||||
| 
 | ||||
| namespace Service::AM::Applets { | ||||
| 
 | ||||
| enum class ShimKind : u32; | ||||
| enum class WebArgTLVType : u16; | ||||
| 
 | ||||
| class WebBrowser final : public Applet { | ||||
| public: | ||||
|     WebBrowser(Core::Frontend::WebBrowserApplet& frontend); | ||||
| @ -38,7 +41,9 @@ private: | ||||
|     bool unpacked = false; | ||||
|     ResultCode status = RESULT_SUCCESS; | ||||
| 
 | ||||
|     FileSys::VirtualFile manual_romfs; | ||||
|     ShimKind kind; | ||||
|     std::map<WebArgTLVType, std::vector<u8>> args; | ||||
| 
 | ||||
|     std::string temporary_dir; | ||||
|     std::string filename; | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Zach Hilman
						Zach Hilman