From 7f442c31f2ed26f4b31c8d702a539c32f3efaa27 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Tue, 9 Jul 2024 16:16:06 +0800 Subject: [PATCH] feat(ios): add app bundle and container path support for hpfile url --- .../ios/module/loader/HippyFileHandler.h | 11 ++- .../ios/module/loader/HippyFileHandler.mm | 37 ++++++++-- tests/ios/HippyFileHandlerTest.mm | 73 +++++++++++++++++++ 3 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 tests/ios/HippyFileHandlerTest.mm diff --git a/framework/ios/module/loader/HippyFileHandler.h b/framework/ios/module/loader/HippyFileHandler.h index 924a9759aff..5d306bc7f1b 100644 --- a/framework/ios/module/loader/HippyFileHandler.h +++ b/framework/ios/module/loader/HippyFileHandler.h @@ -30,7 +30,7 @@ class HippyFileHandler : public VFSUriHandler { public: HippyFileHandler() = delete; HippyFileHandler(HippyBridge *bridge); - + virtual void RequestUntrustedContent( std::shared_ptr request, std::shared_ptr response, @@ -40,12 +40,19 @@ class HippyFileHandler : public VFSUriHandler { std::function)> cb, std::function()> next) override; + /// Convert relative addresses(such as hpfile://) to absolute paths + /// - Parameters: + /// - hippyFileUrl: file url + /// - hippySandboxDirectory: sandbox directory of hippy app + static NSURL *AbsoluteURLFromHippyFileURL(NSURL *hippyFileUrl, NSURL *hippySandboxDirectory); + virtual void RequestUntrustedContent(NSURLRequest *request, NSDictionary *extraInfo, NSOperationQueue *queue, VFSHandlerProgressBlock progress, - VFSHandlerCompletionBlock completion, + VFSHandlerCompletionBlock completion, VFSGetNextHandlerBlock next) override; + private: __weak HippyBridge *bridge_; }; diff --git a/framework/ios/module/loader/HippyFileHandler.mm b/framework/ios/module/loader/HippyFileHandler.mm index 2532c5f53cf..8d8678ecf9e 100644 --- a/framework/ios/module/loader/HippyFileHandler.mm +++ b/framework/ios/module/loader/HippyFileHandler.mm @@ -22,7 +22,6 @@ #import "HippyBridge.h" #import "HippyUtils.h" - #include "HippyFileHandler.h" #include "footstone/logging.h" @@ -42,6 +41,35 @@ FOOTSTONE_UNIMPLEMENTED(); } +NSURL *HippyFileHandler::AbsoluteURLFromHippyFileURL(NSURL *fileUrl, NSURL *hippySandboxDirectory) { + static NSString *defaultHippyLocalFileURLPrefix = @"hpfile://"; + static NSString *hippyLocalRelativeFilePathPrefix = @"./"; + static NSString *hippyLocalAppBundleFilePathPrefix = @"appbundle/"; + static NSString *hippyLocalContainerFilePathPrefix = @"container/"; + + NSURL *absoluteURL = fileUrl; + NSString *urlString = [fileUrl absoluteString]; + if ([urlString hasPrefix:defaultHippyLocalFileURLPrefix]) { + NSString *path = [urlString substringFromIndex:[defaultHippyLocalFileURLPrefix length]]; + + if ([path hasPrefix:hippyLocalRelativeFilePathPrefix]) { + // Hippy Sandbox Relative Path + NSString *relativePath = [path substringFromIndex:hippyLocalRelativeFilePathPrefix.length]; + absoluteURL = [NSURL fileURLWithPath:relativePath relativeToURL:hippySandboxDirectory]; + } else if ([path hasPrefix:hippyLocalAppBundleFilePathPrefix]) { + // App Bundle Path + NSString *relativePath = [path substringFromIndex:[hippyLocalAppBundleFilePathPrefix length]]; + absoluteURL = [[NSBundle mainBundle] URLForResource:relativePath withExtension:nil]; + } else if ([path hasPrefix:hippyLocalContainerFilePathPrefix]) { + // App Container Path + NSString *relativePath = [path substringFromIndex:[hippyLocalContainerFilePathPrefix length]]; + NSString *containerPath = [NSHomeDirectory() stringByAppendingPathComponent:relativePath]; + absoluteURL = [NSURL fileURLWithPath:containerPath]; + } + } + return absoluteURL; +} + void HippyFileHandler::RequestUntrustedContent(NSURLRequest *request, NSDictionary *extraInfo, NSOperationQueue *queue, @@ -62,12 +90,7 @@ return; } - NSURL *absoluteURL = url; - static NSString *defaultHippyLocalFileURLPrefix = @"hpfile://."; - if ([[url absoluteString] hasPrefix:defaultHippyLocalFileURLPrefix]) { - NSString *path = [[url absoluteString] substringFromIndex:[defaultHippyLocalFileURLPrefix length] - 1]; - absoluteURL = [NSURL fileURLWithPath:path relativeToURL:bridge.sandboxDirectory]; - } + NSURL *absoluteURL = AbsoluteURLFromHippyFileURL(url, bridge.sandboxDirectory); if ([absoluteURL isFileURL] || [absoluteURL isFileReferenceURL]) { void (^opBlock)() = ^{ NSError *error; diff --git a/tests/ios/HippyFileHandlerTest.mm b/tests/ios/HippyFileHandlerTest.mm new file mode 100644 index 00000000000..dd98c276155 --- /dev/null +++ b/tests/ios/HippyFileHandlerTest.mm @@ -0,0 +1,73 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +@interface HippyFileHandlerTest : XCTestCase + +/// Test sandboxDirectory for file handler +@property (nonatomic, strong) NSURL *sandboxDirectory; + +@end + +@implementation HippyFileHandlerTest + +- (void)setUp { + self.sandboxDirectory = [NSURL fileURLWithPath:@"/path/to/sandbox"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testAbsoluteURLFromHippyFileURL_AppBundlePath { + NSURL *fileUrl = [NSURL URLWithString:@"hpfile://appbundle/testfile.txt"]; + NSURL *expectedURL = [[NSBundle mainBundle] URLForResource:@"testfile" withExtension:@"txt"]; + NSURL *resultURL = HippyFileHandler::AbsoluteURLFromHippyFileURL(fileUrl,self.sandboxDirectory); + XCTAssertEqualObjects(resultURL, expectedURL, @"The URLs should be equal for app bundle paths."); +} + +- (void)testAbsoluteURLFromHippyFileURL_ContainerPath { + NSURL *fileUrl = [NSURL URLWithString:@"hpfile://container/Documents/testfile.txt"]; + NSString *containerPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/testfile.txt"]; + NSURL *expectedURL = [NSURL fileURLWithPath:containerPath]; + NSURL *resultURL = HippyFileHandler::AbsoluteURLFromHippyFileURL(fileUrl,self.sandboxDirectory); + XCTAssertEqualObjects(resultURL, expectedURL, @"The URLs should be equal for container paths."); +} + +- (void)testAbsoluteURLFromHippyFileURL_SandboxRelativePath { + NSURL *fileUrl = [NSURL URLWithString:@"hpfile://./testfile.txt"]; + NSURL *expectedURL = [NSURL fileURLWithPath:@"testfile.txt" relativeToURL:self.sandboxDirectory]; + NSURL *resultURL = HippyFileHandler::AbsoluteURLFromHippyFileURL(fileUrl,self.sandboxDirectory); + XCTAssertEqualObjects(resultURL, expectedURL, @"The URLs should be equal for sandbox relative paths."); +} + +- (void)testAbsoluteURLFromHippyFileURL_InvalidPrefix { + NSURL *fileUrl = [NSURL URLWithString:@"invalid://testfile.txt"]; + NSURL *expectedURL = fileUrl; + NSURL *resultURL = HippyFileHandler::AbsoluteURLFromHippyFileURL(fileUrl,self.sandboxDirectory); + XCTAssertEqualObjects(resultURL, expectedURL, @"The URLs should be equal for invalid prefixes."); +} + +@end