Brak opisu

WebViewJavascriptBridge.m 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // WebViewJavascriptBridge.m
  3. // ExampleApp-iOS
  4. //
  5. // Created by Marcus Westin on 6/14/13.
  6. // Copyright (c) 2013 Marcus Westin. All rights reserved.
  7. //
  8. #import "WebViewJavascriptBridge.h"
  9. #if defined(supportsWKWebView)
  10. #import "WKWebViewJavascriptBridge.h"
  11. #endif
  12. #if __has_feature(objc_arc_weak)
  13. #define WVJB_WEAK __weak
  14. #else
  15. #define WVJB_WEAK __unsafe_unretained
  16. #endif
  17. @implementation WebViewJavascriptBridge {
  18. WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView;
  19. WVJB_WEAK id _webViewDelegate;
  20. long _uniqueId;
  21. WebViewJavascriptBridgeBase *_base;
  22. }
  23. /* API
  24. *****/
  25. + (void)enableLogging {
  26. [WebViewJavascriptBridgeBase enableLogging];
  27. }
  28. + (void)setLogMaxLength:(int)length {
  29. [WebViewJavascriptBridgeBase setLogMaxLength:length];
  30. }
  31. + (instancetype)bridgeForWebView:(id)webView {
  32. return [self bridge:webView];
  33. }
  34. + (instancetype)bridge:(id)webView {
  35. #if defined supportsWKWebView
  36. if ([webView isKindOfClass:[WKWebView class]]) {
  37. return (WebViewJavascriptBridge*) [WKWebViewJavascriptBridge bridgeForWebView:webView];
  38. }
  39. #endif
  40. if ([webView isKindOfClass:[WVJB_WEBVIEW_TYPE class]]) {
  41. WebViewJavascriptBridge* bridge = [[self alloc] init];
  42. [bridge _platformSpecificSetup:webView];
  43. return bridge;
  44. }
  45. [NSException raise:@"BadWebViewType" format:@"Unknown web view type."];
  46. return nil;
  47. }
  48. - (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate {
  49. _webViewDelegate = webViewDelegate;
  50. }
  51. - (void)send:(id)data {
  52. [self send:data responseCallback:nil];
  53. }
  54. - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback {
  55. [_base sendData:data responseCallback:responseCallback handlerName:nil];
  56. }
  57. - (void)callHandler:(NSString *)handlerName {
  58. [self callHandler:handlerName data:nil responseCallback:nil];
  59. }
  60. - (void)callHandler:(NSString *)handlerName data:(id)data {
  61. [self callHandler:handlerName data:data responseCallback:nil];
  62. }
  63. - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback {
  64. [_base sendData:data responseCallback:responseCallback handlerName:handlerName];
  65. }
  66. - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
  67. _base.messageHandlers[handlerName] = [handler copy];
  68. }
  69. - (void)removeHandler:(NSString *)handlerName {
  70. [_base.messageHandlers removeObjectForKey:handlerName];
  71. }
  72. - (void)disableJavscriptAlertBoxSafetyTimeout {
  73. [_base disableJavscriptAlertBoxSafetyTimeout];
  74. }
  75. /* Platform agnostic internals
  76. *****************************/
  77. - (void)dealloc {
  78. [self _platformSpecificDealloc];
  79. _base = nil;
  80. _webView = nil;
  81. _webViewDelegate = nil;
  82. }
  83. - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand {
  84. return [_webView stringByEvaluatingJavaScriptFromString:javascriptCommand];
  85. }
  86. #if defined WVJB_PLATFORM_OSX
  87. /* Platform specific internals: OSX
  88. **********************************/
  89. - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView {
  90. _webView = webView;
  91. _webView.policyDelegate = self;
  92. _base = [[WebViewJavascriptBridgeBase alloc] init];
  93. _base.delegate = self;
  94. }
  95. - (void) _platformSpecificDealloc {
  96. _webView.policyDelegate = nil;
  97. }
  98. - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
  99. if (webView != _webView) { return; }
  100. NSURL *url = [request URL];
  101. if ([_base isWebViewJavascriptBridgeURL:url]) {
  102. if ([_base isBridgeLoadedURL:url]) {
  103. [_base injectJavascriptFile];
  104. } else if ([_base isQueueMessageURL:url]) {
  105. NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
  106. [_base flushMessageQueue:messageQueueString];
  107. } else {
  108. [_base logUnkownMessage:url];
  109. }
  110. [listener ignore];
  111. } else if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) {
  112. [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener];
  113. } else {
  114. [listener use];
  115. }
  116. }
  117. #elif defined WVJB_PLATFORM_IOS
  118. /* Platform specific internals: iOS
  119. **********************************/
  120. - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView {
  121. _webView = webView;
  122. _webView.delegate = self;
  123. _base = [[WebViewJavascriptBridgeBase alloc] init];
  124. _base.delegate = self;
  125. }
  126. - (void) _platformSpecificDealloc {
  127. _webView.delegate = nil;
  128. }
  129. - (void)webViewDidFinishLoad:(UIWebView *)webView {
  130. if (webView != _webView) { return; }
  131. __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
  132. if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
  133. [strongDelegate webViewDidFinishLoad:webView];
  134. }
  135. }
  136. - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
  137. if (webView != _webView) { return; }
  138. __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
  139. if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
  140. [strongDelegate webView:webView didFailLoadWithError:error];
  141. }
  142. }
  143. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
  144. if (webView != _webView) { return YES; }
  145. NSURL *url = [request URL];
  146. __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
  147. if ([_base isWebViewJavascriptBridgeURL:url]) {
  148. if ([_base isBridgeLoadedURL:url]) {
  149. [_base injectJavascriptFile];
  150. } else if ([_base isQueueMessageURL:url]) {
  151. NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
  152. [_base flushMessageQueue:messageQueueString];
  153. } else {
  154. [_base logUnkownMessage:url];
  155. }
  156. return NO;
  157. } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
  158. return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
  159. } else {
  160. return YES;
  161. }
  162. }
  163. - (void)webViewDidStartLoad:(UIWebView *)webView {
  164. if (webView != _webView) { return; }
  165. __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
  166. if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
  167. [strongDelegate webViewDidStartLoad:webView];
  168. }
  169. }
  170. #endif
  171. @end