@@ -19,99 +19,104 @@ Licensed to the Apache Software Foundation (ASF) under one
19
19
20
20
21
21
#import " CDVURLSchemeHandler.h"
22
+ #import < Cordova/CDVViewController.h>
23
+ #import < Cordova/CDVPlugin.h>
24
+ #import < Foundation/Foundation.h>
22
25
#import < MobileCoreServices/MobileCoreServices.h>
23
26
24
- # import < objc/message.h >
27
+ @interface CDVURLSchemeHandler ()
25
28
26
- @implementation CDVURLSchemeHandler
29
+ @property (nonatomic , weak ) CDVViewController *viewController;
30
+ @property (nonatomic ) NSMapTable <id <WKURLSchemeTask >, CDVPlugin <CDVPluginSchemeHandler> *> *handlerMap;
31
+
32
+ @end
27
33
34
+ @implementation CDVURLSchemeHandler
28
35
29
- - (instancetype )initWithVC : (CDVViewController *)controller
36
+ - (instancetype )initWithViewController : (CDVViewController *)controller
30
37
{
31
38
self = [super init ];
32
39
if (self) {
33
40
_viewController = controller;
41
+ _handlerMap = [NSMapTable weakToWeakObjectsMapTable ];
34
42
}
35
43
return self;
36
44
}
37
45
38
46
- (void )webView : (WKWebView *)webView startURLSchemeTask : (id <WKURLSchemeTask >)urlSchemeTask
39
47
{
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
+
40
64
NSString * startPath = [[NSBundle mainBundle ] pathForResource: self .viewController.webContentFolderName ofType: nil ];
41
65
NSURL * url = urlSchemeTask.request .URL ;
42
66
NSString * stringToLoad = url.path ;
43
67
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
- }
65
68
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];
70
75
} 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];
76
77
}
77
78
}
79
+ }
78
80
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
+ }
100
102
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];
106
106
}
107
+ [urlSchemeTask didFinish ];
108
+
109
+ [self .handlerMap removeObjectForKey: urlSchemeTask];
107
110
}
108
111
109
- - (void )webView : (nonnull WKWebView *)webView stopURLSchemeTask : (nonnull id <WKURLSchemeTask >)urlSchemeTask
112
+ - (void )webView : (WKWebView *)webView stopURLSchemeTask : (id <WKURLSchemeTask >)urlSchemeTask
110
113
{
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] ;
114
117
}
118
+
119
+ [self .handlerMap removeObjectForKey: urlSchemeTask];
115
120
}
116
121
117
122
-(NSString *) getMimeType : (NSString *)fileExtension {
0 commit comments