@@ -19,99 +19,104 @@ Licensed to the Apache Software Foundation (ASF) under one
1919
2020
2121#import " CDVURLSchemeHandler.h"
22+ #import < Cordova/CDVViewController.h>
23+ #import < Cordova/CDVPlugin.h>
24+ #import < Foundation/Foundation.h>
2225#import < MobileCoreServices/MobileCoreServices.h>
2326
24- # import < objc/message.h >
27+ @interface CDVURLSchemeHandler ()
2528
26- @implementation CDVURLSchemeHandler
29+ @property (nonatomic , weak ) CDVViewController *viewController;
30+ @property (nonatomic ) NSMapTable <id <WKURLSchemeTask >, CDVPlugin <CDVPluginSchemeHandler> *> *handlerMap;
31+
32+ @end
2733
34+ @implementation CDVURLSchemeHandler
2835
29- - (instancetype )initWithVC : (CDVViewController *)controller
36+ - (instancetype )initWithViewController : (CDVViewController *)controller
3037{
3138 self = [super init ];
3239 if (self) {
3340 _viewController = controller;
41+ _handlerMap = [NSMapTable weakToWeakObjectsMapTable ];
3442 }
3543 return self;
3644}
3745
3846- (void )webView : (WKWebView *)webView startURLSchemeTask : (id <WKURLSchemeTask >)urlSchemeTask
3947{
48+ // Give plugins the chance to handle the url
49+ for (CDVPlugin *plugin in self.viewController .enumerablePlugins ) {
50+ if ([plugin respondsToSelector: @selector (overrideSchemeTask: )]) {
51+ CDVPlugin <CDVPluginSchemeHandler> *schemePlugin = (CDVPlugin<CDVPluginSchemeHandler> *)plugin;
52+ if ([schemePlugin overrideSchemeTask: urlSchemeTask]) {
53+ // Store the plugin that is handling this particular request
54+ [self .handlerMap setObject: schemePlugin forKey: urlSchemeTask];
55+ return ;
56+ }
57+ }
58+ }
59+
60+ // Indicate that we are handling this task, by adding an entry with a null plugin
61+ // We do this so that we can (in future) detect if the task is cancelled before we finished feeding it response data
62+ [self .handlerMap setObject: (id )[NSNull null ] forKey: urlSchemeTask];
63+
4064 NSString * startPath = [[NSBundle mainBundle ] pathForResource: self .viewController.webContentFolderName ofType: nil ];
4165 NSURL * url = urlSchemeTask.request .URL ;
4266 NSString * stringToLoad = url.path ;
4367 NSString * scheme = url.scheme ;
44-
45- CDVViewController* vc = (CDVViewController*)self.viewController ;
46-
47- /*
48- * Give plugins the chance to handle the url
49- */
50- BOOL anyPluginsResponded = NO ;
51- BOOL handledRequest = NO ;
52-
53- NSDictionary *pluginObjects = [[vc pluginObjects ] copy ];
54- for (NSString * pluginName in pluginObjects) {
55- self.schemePlugin = [vc.pluginObjects objectForKey: pluginName];
56- SEL selector = NSSelectorFromString (@" overrideSchemeTask:" );
57- if ([self .schemePlugin respondsToSelector: selector]) {
58- handledRequest = (((BOOL (*)(id , SEL , id <WKURLSchemeTask >))objc_msgSend)(self.schemePlugin , selector, urlSchemeTask));
59- if (handledRequest) {
60- anyPluginsResponded = YES ;
61- break ;
62- }
63- }
64- }
6568
66- if (!anyPluginsResponded) {
67- if ([scheme isEqualToString: self .viewController.appScheme]) {
68- if ([stringToLoad hasPrefix: @" /_app_file_" ]) {
69- startPath = [stringToLoad stringByReplacingOccurrencesOfString: @" /_app_file_" withString: @" " ];
69+ if ([scheme isEqualToString: self .viewController.appScheme]) {
70+ if ([stringToLoad hasPrefix: @" /_app_file_" ]) {
71+ startPath = [stringToLoad stringByReplacingOccurrencesOfString: @" /_app_file_" withString: @" " ];
72+ } else {
73+ if ([stringToLoad isEqualToString: @" " ] || [url.pathExtension isEqualToString: @" " ]) {
74+ startPath = [startPath stringByAppendingPathComponent: self .viewController.startPage];
7075 } else {
71- if ([stringToLoad isEqualToString: @" " ] || [url.pathExtension isEqualToString: @" " ]) {
72- startPath = [startPath stringByAppendingPathComponent: self .viewController.startPage];
73- } else {
74- startPath = [startPath stringByAppendingPathComponent: stringToLoad];
75- }
76+ startPath = [startPath stringByAppendingPathComponent: stringToLoad];
7677 }
7778 }
79+ }
7880
79- NSError * fileError = nil ;
80- NSData * data = nil ;
81- if ([self isMediaExtension: url.pathExtension]) {
82- data = [NSData dataWithContentsOfFile: startPath options: NSDataReadingMappedIfSafe error: &fileError];
83- }
84- if (!data || fileError) {
85- data = [[NSData alloc ] initWithContentsOfFile: startPath];
86- }
87- NSInteger statusCode = 200 ;
88- if (!data) {
89- statusCode = 404 ;
90- }
91- NSURL * localUrl = [NSURL URLWithString: url.absoluteString];
92- NSString * mimeType = [self getMimeType: url.pathExtension];
93- id response = nil ;
94- if (data && [self isMediaExtension: url.pathExtension]) {
95- response = [[NSURLResponse alloc ] initWithURL: localUrl MIMEType: mimeType expectedContentLength: data.length textEncodingName: nil ];
96- } else {
97- NSDictionary * headers = @{ @" Content-Type" : mimeType, @" Cache-Control" : @" no-cache" };
98- response = [[NSHTTPURLResponse alloc ] initWithURL: localUrl statusCode: statusCode HTTPVersion: nil headerFields: headers];
99- }
81+ NSError * fileError = nil ;
82+ NSData * data = nil ;
83+ if ([self isMediaExtension: url.pathExtension]) {
84+ data = [NSData dataWithContentsOfFile: startPath options: NSDataReadingMappedIfSafe error: &fileError];
85+ }
86+ if (!data || fileError) {
87+ data = [[NSData alloc ] initWithContentsOfFile: startPath];
88+ }
89+ NSInteger statusCode = 200 ;
90+ if (!data) {
91+ statusCode = 404 ;
92+ }
93+ NSURL * localUrl = [NSURL URLWithString: url.absoluteString];
94+ NSString * mimeType = [self getMimeType: url.pathExtension];
95+ id response = nil ;
96+ if (data && [self isMediaExtension: url.pathExtension]) {
97+ response = [[NSURLResponse alloc ] initWithURL: localUrl MIMEType: mimeType expectedContentLength: data.length textEncodingName: nil ];
98+ } else {
99+ NSDictionary * headers = @{ @" Content-Type" : mimeType, @" Cache-Control" : @" no-cache" };
100+ response = [[NSHTTPURLResponse alloc ] initWithURL: localUrl statusCode: statusCode HTTPVersion: nil headerFields: headers];
101+ }
100102
101- [urlSchemeTask didReceiveResponse: response];
102- if (data) {
103- [urlSchemeTask didReceiveData: data];
104- }
105- [urlSchemeTask didFinish ];
103+ [urlSchemeTask didReceiveResponse: response];
104+ if (data) {
105+ [urlSchemeTask didReceiveData: data];
106106 }
107+ [urlSchemeTask didFinish ];
108+
109+ [self .handlerMap removeObjectForKey: urlSchemeTask];
107110}
108111
109- - (void )webView : (nonnull WKWebView *)webView stopURLSchemeTask : (nonnull id <WKURLSchemeTask >)urlSchemeTask
112+ - (void )webView : (WKWebView *)webView stopURLSchemeTask : (id <WKURLSchemeTask >)urlSchemeTask
110113{
111- SEL selector = NSSelectorFromString ( @" stopSchemeTask: " ) ;
112- if (self. schemePlugin != nil && [self .schemePlugin respondsToSelector: selector]) {
113- ((( void (*)( id , SEL , id < WKURLSchemeTask >))objc_msgSend)(self. schemePlugin , selector, urlSchemeTask)) ;
114+ CDVPlugin <CDVPluginSchemeHandler> *plugin = [ self .handlerMap objectForKey: urlSchemeTask] ;
115+ if (![plugin isEqual: [ NSNull null ]] && [plugin respondsToSelector: @ selector( stopSchemeTask: ) ]) {
116+ [plugin stopSchemeTask: urlSchemeTask] ;
114117 }
118+
119+ [self .handlerMap removeObjectForKey: urlSchemeTask];
115120}
116121
117122-(NSString *) getMimeType : (NSString *)fileExtension {
0 commit comments