You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CULPlugin.m 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // CULPlugin.m
  3. //
  4. // Created by Nikolay Demyankov on 14.09.15.
  5. //
  6. #import "CULPlugin.h"
  7. #import "CULConfigXmlParser.h"
  8. #import "CULPath.h"
  9. #import "CULHost.h"
  10. #import "CDVPluginResult+CULPlugin.h"
  11. #import "CDVInvokedUrlCommand+CULPlugin.h"
  12. #import "CULConfigJsonParser.h"
  13. @interface CULPlugin() {
  14. NSArray *_supportedHosts;
  15. CDVPluginResult *_storedEvent;
  16. NSMutableDictionary<NSString *, NSString *> *_subscribers;
  17. }
  18. @end
  19. @implementation CULPlugin
  20. #pragma mark Public API
  21. - (void)pluginInitialize {
  22. [self localInit];
  23. // Can be used for testing.
  24. // Just uncomment, close the app and reopen it. That will simulate application launch from the link.
  25. // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume:) name:UIApplicationWillEnterForegroundNotification object:nil];
  26. }
  27. //- (void)onResume:(NSNotification *)notification {
  28. // NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb];
  29. // [activity setWebpageURL:[NSURL URLWithString:@"http://site2.com/news/page?q=1&v=2#myhash"]];
  30. //
  31. // [self handleUserActivity:activity];
  32. //}
  33. - (void)handleOpenURL:(NSNotification*)notification {
  34. id url = notification.object;
  35. if (![url isKindOfClass:[NSURL class]]) {
  36. return;
  37. }
  38. CULHost *host = [self findHostByURL:url];
  39. if (host) {
  40. [self storeEventWithHost:host originalURL:url];
  41. }
  42. }
  43. - (BOOL)handleUserActivity:(NSUserActivity *)userActivity {
  44. [self localInit];
  45. NSURL *launchURL = userActivity.webpageURL;
  46. CULHost *host = [self findHostByURL:launchURL];
  47. if (host == nil) {
  48. return NO;
  49. }
  50. [self storeEventWithHost:host originalURL:launchURL];
  51. return YES;
  52. }
  53. - (void)onAppTerminate {
  54. _supportedHosts = nil;
  55. _subscribers = nil;
  56. _storedEvent = nil;
  57. [super onAppTerminate];
  58. }
  59. #pragma mark Private API
  60. - (void)localInit {
  61. if (_supportedHosts) {
  62. return;
  63. }
  64. _subscribers = [[NSMutableDictionary alloc] init];
  65. // Get supported hosts from the config.xml or www/ul.json.
  66. // For now priority goes to json config.
  67. _supportedHosts = [self getSupportedHostsFromPreferences];
  68. }
  69. - (NSArray<CULHost *> *)getSupportedHostsFromPreferences {
  70. NSString *jsonConfigPath = [[NSBundle mainBundle] pathForResource:@"ul" ofType:@"json" inDirectory:@"www"];
  71. if (jsonConfigPath) {
  72. return [CULConfigJsonParser parseConfig:jsonConfigPath];
  73. }
  74. return [CULConfigXmlParser parse];
  75. }
  76. /**
  77. * Store event data for future use.
  78. * If we are resuming the app - try to consume it.
  79. *
  80. * @param host host that matches the launch url
  81. * @param originalUrl launch url
  82. */
  83. - (void)storeEventWithHost:(CULHost *)host originalURL:(NSURL *)originalUrl {
  84. _storedEvent = [CDVPluginResult resultWithHost:host originalURL:originalUrl];
  85. [self tryToConsumeEvent];
  86. }
  87. /**
  88. * Find host entry that corresponds to launch url.
  89. *
  90. * @param launchURL url that launched the app
  91. * @return host entry; <code>nil</code> if none is found
  92. */
  93. - (CULHost *)findHostByURL:(NSURL *)launchURL {
  94. NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:launchURL resolvingAgainstBaseURL:YES];
  95. CULHost *host = nil;
  96. for (CULHost *supportedHost in _supportedHosts) {
  97. NSPredicate *pred = [NSPredicate predicateWithFormat:@"self LIKE[c] %@", supportedHost.name];
  98. if ([pred evaluateWithObject:urlComponents.host]) {
  99. host = supportedHost;
  100. break;
  101. }
  102. }
  103. return host;
  104. }
  105. #pragma mark Methods to send data to JavaScript
  106. /**
  107. * Try to send event to the web page.
  108. * If there is a subscriber for the event - it will be consumed.
  109. * If not - it will stay until someone subscribes to it.
  110. */
  111. - (void)tryToConsumeEvent {
  112. if (_subscribers.count == 0 || _storedEvent == nil) {
  113. return;
  114. }
  115. NSString *storedEventName = [_storedEvent eventName];
  116. for (NSString *eventName in _subscribers) {
  117. if ([storedEventName isEqualToString:eventName]) {
  118. NSString *callbackID = _subscribers[eventName];
  119. [self.commandDelegate sendPluginResult:_storedEvent callbackId:callbackID];
  120. _storedEvent = nil;
  121. break;
  122. }
  123. }
  124. }
  125. #pragma mark Methods, available from JavaScript side
  126. - (void)jsSubscribeForEvent:(CDVInvokedUrlCommand *)command {
  127. NSString *eventName = [command eventName];
  128. if (eventName.length == 0) {
  129. return;
  130. }
  131. _subscribers[eventName] = command.callbackId;
  132. [self tryToConsumeEvent];
  133. }
  134. - (void)jsUnsubscribeFromEvent:(CDVInvokedUrlCommand *)command {
  135. NSString *eventName = [command eventName];
  136. if (eventName.length == 0) {
  137. return;
  138. }
  139. [_subscribers removeObjectForKey:eventName];
  140. }
  141. @end