@thathoff/cordova-plugin-universal-links 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/LICENSE +22 -0
  3. package/README.md +908 -0
  4. package/docs/images/app-associated-domains.jpg +0 -0
  5. package/docs/images/app-id-team-prefix.jpg +0 -0
  6. package/docs/images/app-id.jpg +0 -0
  7. package/docs/images/branch-io-link-domain.jpg +0 -0
  8. package/docs/images/branch-io.jpg +0 -0
  9. package/docs/images/developer-console.jpg +0 -0
  10. package/hooks/afterPrepareHook.js +86 -0
  11. package/hooks/beforePluginInstallHook.js +55 -0
  12. package/hooks/iosBeforePrepareHook.js +74 -0
  13. package/hooks/lib/android/manifestWriter.js +320 -0
  14. package/hooks/lib/android/webSiteHook.js +162 -0
  15. package/hooks/lib/configXmlHelper.js +117 -0
  16. package/hooks/lib/configXmlParser.js +145 -0
  17. package/hooks/lib/ios/appleAppSiteAssociationFile.js +173 -0
  18. package/hooks/lib/ios/projectEntitlements.js +174 -0
  19. package/hooks/lib/ios/xcodePreferences.js +243 -0
  20. package/hooks/lib/xmlHelper.js +57 -0
  21. package/package.json +58 -0
  22. package/plugin.xml +106 -0
  23. package/src/android/com/nordnetab/cordova/ul/UniversalLinksPlugin.java +221 -0
  24. package/src/android/com/nordnetab/cordova/ul/js/JSAction.java +19 -0
  25. package/src/android/com/nordnetab/cordova/ul/model/JSMessage.java +193 -0
  26. package/src/android/com/nordnetab/cordova/ul/model/ULHost.java +85 -0
  27. package/src/android/com/nordnetab/cordova/ul/model/ULPath.java +43 -0
  28. package/src/android/com/nordnetab/cordova/ul/parser/ULConfigXmlParser.java +156 -0
  29. package/src/android/com/nordnetab/cordova/ul/parser/XmlTags.java +49 -0
  30. package/src/ios/AppDelegate+CULPlugin.h +17 -0
  31. package/src/ios/AppDelegate+CULPlugin.m +32 -0
  32. package/src/ios/CULPlugin.h +38 -0
  33. package/src/ios/CULPlugin.m +176 -0
  34. package/src/ios/JS/CDVInvokedUrlCommand+CULPlugin.h +21 -0
  35. package/src/ios/JS/CDVInvokedUrlCommand+CULPlugin.m +19 -0
  36. package/src/ios/JS/CDVPluginResult+CULPlugin.h +29 -0
  37. package/src/ios/JS/CDVPluginResult+CULPlugin.m +157 -0
  38. package/src/ios/Model/CULHost.h +63 -0
  39. package/src/ios/Model/CULHost.m +50 -0
  40. package/src/ios/Model/CULPath.h +36 -0
  41. package/src/ios/Model/CULPath.m +21 -0
  42. package/src/ios/Parser/JSON/CULConfigJsonParser.h +22 -0
  43. package/src/ios/Parser/JSON/CULConfigJsonParser.m +60 -0
  44. package/src/ios/Parser/XML/CULConfigXmlParser.h +22 -0
  45. package/src/ios/Parser/XML/CULConfigXmlParser.m +123 -0
  46. package/src/ios/Parser/XML/CULXmlTags.h +54 -0
  47. package/src/ios/Parser/XML/CULXmlTags.m +22 -0
  48. package/src/ios/Utils/NSBundle+CULPlugin.h +22 -0
  49. package/src/ios/Utils/NSBundle+CULPlugin.m +15 -0
  50. package/ul_web_hooks/android_web_hook_tpl.html +23 -0
  51. package/www/universal_links.js +56 -0
@@ -0,0 +1,156 @@
1
+ package com.nordnetab.cordova.ul.parser;
2
+
3
+ import android.content.Context;
4
+ import android.text.TextUtils;
5
+
6
+ import com.nordnetab.cordova.ul.model.ULHost;
7
+ import com.nordnetab.cordova.ul.model.ULPath;
8
+
9
+ import org.apache.cordova.ConfigXmlParser;
10
+ import org.xmlpull.v1.XmlPullParser;
11
+
12
+ import java.util.ArrayList;
13
+ import java.util.List;
14
+
15
+ /**
16
+ * Created by Nikolay Demyankov on 09.09.15.
17
+ * <p/>
18
+ * Parser for config.xml. Reads only plugin-specific preferences.
19
+ */
20
+ public class ULConfigXmlParser extends ConfigXmlParser {
21
+
22
+ private final Context context;
23
+ private List<ULHost> hostsList;
24
+
25
+ private boolean isInsideMainTag;
26
+ private boolean didParseMainBlock;
27
+ private boolean isInsideHostBlock;
28
+ private ULHost processedHost;
29
+
30
+ // region Public API
31
+
32
+ /**
33
+ * Constructor
34
+ *
35
+ * @param context application context
36
+ */
37
+ public ULConfigXmlParser(Context context) {
38
+ this.context = context;
39
+ }
40
+
41
+ /**
42
+ * Parse config.xml
43
+ *
44
+ * @return list of hosts, defined in the config file
45
+ */
46
+ public List<ULHost> parse() {
47
+ resetValuesToDefaultState();
48
+ super.parse(context);
49
+
50
+ return hostsList;
51
+ }
52
+
53
+ // endregion
54
+
55
+ // region XML processing
56
+
57
+ @Override
58
+ public void handleStartTag(XmlPullParser xml) {
59
+ if (didParseMainBlock) {
60
+ return;
61
+ }
62
+
63
+ final String name = xml.getName();
64
+ if (!isInsideMainTag && XmlTags.MAIN_TAG.equals(name)) {
65
+ isInsideMainTag = true;
66
+ return;
67
+ }
68
+
69
+ if (!isInsideMainTag) {
70
+ return;
71
+ }
72
+
73
+ if (!isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
74
+ isInsideHostBlock = true;
75
+ processHostBlock(xml);
76
+ return;
77
+ }
78
+
79
+ if (isInsideHostBlock && XmlTags.PATH_TAG.equals(name)) {
80
+ processPathBlock(xml);
81
+ }
82
+ }
83
+
84
+ @Override
85
+ public void handleEndTag(XmlPullParser xml) {
86
+ if (didParseMainBlock) {
87
+ return;
88
+ }
89
+
90
+ final String name = xml.getName();
91
+
92
+ if (isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
93
+ isInsideHostBlock = false;
94
+ hostsList.add(processedHost);
95
+ processedHost = null;
96
+ return;
97
+ }
98
+
99
+ if (XmlTags.MAIN_TAG.equals(name)) {
100
+ isInsideMainTag = false;
101
+ didParseMainBlock = true;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Parse <host />
107
+ */
108
+ private void processHostBlock(XmlPullParser xml) {
109
+ final String hostName = xml.getAttributeValue(null, XmlTags.HOST_NAME_ATTRIBUTE);
110
+ final String eventName = xml.getAttributeValue(null, XmlTags.HOST_EVENT_ATTRIBUTE);
111
+ final String scheme = xml.getAttributeValue(null, XmlTags.HOST_SCHEME_ATTRIBUTE);
112
+
113
+ processedHost = new ULHost(hostName, scheme, eventName);
114
+ }
115
+
116
+ /**
117
+ * Parse <path />
118
+ */
119
+ private void processPathBlock(XmlPullParser xml) {
120
+ final String url = xml.getAttributeValue(null, XmlTags.PATH_URL_TAG);
121
+ String event = xml.getAttributeValue(null, XmlTags.PATH_EVENT_TAG);
122
+
123
+ // skip wildcard urls
124
+ if ("*".equals(url) || ".*".equals(url)) {
125
+ // but if path has event name - set it to host
126
+ if (!TextUtils.isEmpty(event)) {
127
+ processedHost.setEvent(event);
128
+ }
129
+
130
+ return;
131
+ }
132
+
133
+ // if event name is empty - use one from the host
134
+ if (TextUtils.isEmpty(event)) {
135
+ event = processedHost.getEvent();
136
+ }
137
+
138
+ // create path entry
139
+ ULPath path = new ULPath(url, event);
140
+ processedHost.getPaths().add(path);
141
+ }
142
+
143
+ // endregion
144
+
145
+ // region Private API
146
+
147
+ private void resetValuesToDefaultState() {
148
+ hostsList = new ArrayList<ULHost>();
149
+ isInsideMainTag = false;
150
+ didParseMainBlock = false;
151
+ isInsideHostBlock = false;
152
+ processedHost = null;
153
+ }
154
+
155
+ // endregion
156
+ }
@@ -0,0 +1,49 @@
1
+ package com.nordnetab.cordova.ul.parser;
2
+
3
+ /**
4
+ * Created by Nikolay Demyankov on 10.09.15.
5
+ * <p/>
6
+ * XML tags that is used in config.xml to specify plugin preferences.
7
+ */
8
+ final class XmlTags {
9
+
10
+ /**
11
+ * Main tag in which we define plugin related stuff
12
+ */
13
+ public static final String MAIN_TAG = "universal-links";
14
+
15
+ /**
16
+ * Host main tag
17
+ */
18
+ public static final String HOST_TAG = "host";
19
+
20
+ /**
21
+ * Scheme attribute for the host entry
22
+ */
23
+ public static final String HOST_SCHEME_ATTRIBUTE = "scheme";
24
+
25
+ /**
26
+ * Name attribute for the host entry
27
+ */
28
+ public static final String HOST_NAME_ATTRIBUTE = "name";
29
+
30
+ /**
31
+ * Event attribute for the host entry
32
+ */
33
+ public static final String HOST_EVENT_ATTRIBUTE = "event";
34
+
35
+ /**
36
+ * Path main tag
37
+ */
38
+ public static final String PATH_TAG = "path";
39
+
40
+ /**
41
+ * Url attribute for the path entry
42
+ */
43
+ public static final String PATH_URL_TAG = "url";
44
+
45
+ /**
46
+ * Event attribute for the path entry
47
+ */
48
+ public static final String PATH_EVENT_TAG = "event";
49
+ }
@@ -0,0 +1,17 @@
1
+ //
2
+ // AppDelegate+CULPlugin.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "AppDelegate.h"
8
+
9
+ /**
10
+ * Category for the AppDelegate that overrides application:continueUserActivity:restorationHandler method,
11
+ * so we could handle application launch when user clicks on the link in the browser.
12
+ */
13
+ @interface AppDelegate (CULPlugin)
14
+
15
+ - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler;
16
+
17
+ @end
@@ -0,0 +1,32 @@
1
+ //
2
+ // AppDelegate+CULPlugin.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "AppDelegate+CULPlugin.h"
8
+ #import "CULPlugin.h"
9
+
10
+ /**
11
+ * Plugin name in config.xml
12
+ */
13
+ static NSString *const PLUGIN_NAME = @"UniversalLinks";
14
+
15
+ @implementation AppDelegate (CULPlugin)
16
+
17
+ - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
18
+ // ignore activities that are not for Universal Links
19
+ if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] || userActivity.webpageURL == nil) {
20
+ return NO;
21
+ }
22
+
23
+ // get instance of the plugin and let it handle the userActivity object
24
+ CULPlugin *plugin = [self.viewController getCommandInstance:PLUGIN_NAME];
25
+ if (plugin == nil) {
26
+ return NO;
27
+ }
28
+
29
+ return [plugin handleUserActivity:userActivity];
30
+ }
31
+
32
+ @end
@@ -0,0 +1,38 @@
1
+ //
2
+ // CULPlugin.h
3
+ //
4
+ // Created by Nikolay Demyankov on 14.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+ #import <Cordova/CDVPlugin.h>
9
+
10
+ /**
11
+ * Plugin main class.
12
+ */
13
+ @interface CULPlugin : CDVPlugin
14
+
15
+ /**
16
+ * Subscribe to event.
17
+ *
18
+ * @param command command from js side with event name and callback id.
19
+ */
20
+ - (void)jsSubscribeForEvent:(CDVInvokedUrlCommand *)command;
21
+
22
+ /**
23
+ * Unsubscribe from event.
24
+ *
25
+ * @param command command from js side with event name
26
+ */
27
+ - (void)jsUnsubscribeFromEvent:(CDVInvokedUrlCommand *)command;
28
+
29
+ /**
30
+ * Try to hanlde application launch when user clicked on the link.
31
+ *
32
+ * @param userActivity object with information about the application launch
33
+ *
34
+ * @return <code>true</code> - if this is a universal link and it is defined in config.xml; otherwise - <code>false</code>
35
+ */
36
+ - (BOOL)handleUserActivity:(NSUserActivity *)userActivity;
37
+
38
+ @end
@@ -0,0 +1,176 @@
1
+ //
2
+ // CULPlugin.m
3
+ //
4
+ // Created by Nikolay Demyankov on 14.09.15.
5
+ //
6
+
7
+ #import "CULPlugin.h"
8
+ #import "CULConfigXmlParser.h"
9
+ #import "CULPath.h"
10
+ #import "CULHost.h"
11
+ #import "CDVPluginResult+CULPlugin.h"
12
+ #import "CDVInvokedUrlCommand+CULPlugin.h"
13
+ #import "CULConfigJsonParser.h"
14
+
15
+ @interface CULPlugin() {
16
+ NSArray *_supportedHosts;
17
+ CDVPluginResult *_storedEvent;
18
+ NSMutableDictionary<NSString *, NSString *> *_subscribers;
19
+ }
20
+
21
+ @end
22
+
23
+ @implementation CULPlugin
24
+
25
+ #pragma mark Public API
26
+
27
+ - (void)pluginInitialize {
28
+ [self localInit];
29
+ // Can be used for testing.
30
+ // Just uncomment, close the app and reopen it. That will simulate application launch from the link.
31
+ // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume:) name:UIApplicationWillEnterForegroundNotification object:nil];
32
+ }
33
+
34
+ //- (void)onResume:(NSNotification *)notification {
35
+ // NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb];
36
+ // [activity setWebpageURL:[NSURL URLWithString:@"http://site2.com/news/page?q=1&v=2#myhash"]];
37
+ //
38
+ // [self handleUserActivity:activity];
39
+ //}
40
+
41
+ - (void)handleOpenURL:(NSNotification*)notification {
42
+ id url = notification.object;
43
+ if (![url isKindOfClass:[NSURL class]]) {
44
+ return;
45
+ }
46
+
47
+ CULHost *host = [self findHostByURL:url];
48
+ if (host) {
49
+ [self storeEventWithHost:host originalURL:url];
50
+ }
51
+ }
52
+
53
+ - (BOOL)handleUserActivity:(NSUserActivity *)userActivity {
54
+ [self localInit];
55
+
56
+ NSURL *launchURL = userActivity.webpageURL;
57
+ CULHost *host = [self findHostByURL:launchURL];
58
+ if (host == nil) {
59
+ return NO;
60
+ }
61
+
62
+ [self storeEventWithHost:host originalURL:launchURL];
63
+
64
+ return YES;
65
+ }
66
+
67
+ - (void)onAppTerminate {
68
+ _supportedHosts = nil;
69
+ _subscribers = nil;
70
+ _storedEvent = nil;
71
+
72
+ [super onAppTerminate];
73
+ }
74
+
75
+ #pragma mark Private API
76
+
77
+ - (void)localInit {
78
+ if (_supportedHosts) {
79
+ return;
80
+ }
81
+
82
+ _subscribers = [[NSMutableDictionary alloc] init];
83
+
84
+ // Get supported hosts from the config.xml or www/ul.json.
85
+ // For now priority goes to json config.
86
+ _supportedHosts = [self getSupportedHostsFromPreferences];
87
+ }
88
+
89
+ - (NSArray<CULHost *> *)getSupportedHostsFromPreferences {
90
+ NSString *jsonConfigPath = [[NSBundle mainBundle] pathForResource:@"ul" ofType:@"json" inDirectory:@"www"];
91
+ if (jsonConfigPath) {
92
+ return [CULConfigJsonParser parseConfig:jsonConfigPath];
93
+ }
94
+
95
+ return [CULConfigXmlParser parse];
96
+ }
97
+
98
+ /**
99
+ * Store event data for future use.
100
+ * If we are resuming the app - try to consume it.
101
+ *
102
+ * @param host host that matches the launch url
103
+ * @param originalUrl launch url
104
+ */
105
+ - (void)storeEventWithHost:(CULHost *)host originalURL:(NSURL *)originalUrl {
106
+ _storedEvent = [CDVPluginResult resultWithHost:host originalURL:originalUrl];
107
+ [self tryToConsumeEvent];
108
+ }
109
+
110
+ /**
111
+ * Find host entry that corresponds to launch url.
112
+ *
113
+ * @param launchURL url that launched the app
114
+ * @return host entry; <code>nil</code> if none is found
115
+ */
116
+ - (CULHost *)findHostByURL:(NSURL *)launchURL {
117
+ NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:launchURL resolvingAgainstBaseURL:YES];
118
+ CULHost *host = nil;
119
+ for (CULHost *supportedHost in _supportedHosts) {
120
+ NSPredicate *pred = [NSPredicate predicateWithFormat:@"self LIKE[c] %@", supportedHost.name];
121
+ if ([pred evaluateWithObject:urlComponents.host]) {
122
+ host = supportedHost;
123
+ break;
124
+ }
125
+ }
126
+
127
+ return host;
128
+ }
129
+
130
+ #pragma mark Methods to send data to JavaScript
131
+
132
+ /**
133
+ * Try to send event to the web page.
134
+ * If there is a subscriber for the event - it will be consumed.
135
+ * If not - it will stay until someone subscribes to it.
136
+ */
137
+ - (void)tryToConsumeEvent {
138
+ if (_subscribers.count == 0 || _storedEvent == nil) {
139
+ return;
140
+ }
141
+
142
+ NSString *storedEventName = [_storedEvent eventName];
143
+ for (NSString *eventName in _subscribers) {
144
+ if ([storedEventName isEqualToString:eventName]) {
145
+ NSString *callbackID = _subscribers[eventName];
146
+ [self.commandDelegate sendPluginResult:_storedEvent callbackId:callbackID];
147
+ _storedEvent = nil;
148
+ break;
149
+ }
150
+ }
151
+ }
152
+
153
+ #pragma mark Methods, available from JavaScript side
154
+
155
+ - (void)jsSubscribeForEvent:(CDVInvokedUrlCommand *)command {
156
+ NSString *eventName = [command eventName];
157
+ if (eventName.length == 0) {
158
+ return;
159
+ }
160
+
161
+ _subscribers[eventName] = command.callbackId;
162
+ [self tryToConsumeEvent];
163
+ }
164
+
165
+ - (void)jsUnsubscribeFromEvent:(CDVInvokedUrlCommand *)command {
166
+ NSString *eventName = [command eventName];
167
+ if (eventName.length == 0) {
168
+ return;
169
+ }
170
+
171
+ [_subscribers removeObjectForKey:eventName];
172
+ }
173
+
174
+
175
+
176
+ @end
@@ -0,0 +1,21 @@
1
+ //
2
+ // CDVInvokedUrlCommand+CULPlugin.h
3
+ //
4
+ // Created by Nikolay Demyankov on 08.12.15.
5
+ //
6
+
7
+ #import <Cordova/CDVPlugin.h>
8
+
9
+ /**
10
+ * Category to get the event name from the request, that is sent from JS side.
11
+ */
12
+ @interface CDVInvokedUrlCommand (CULPlugin)
13
+
14
+ /**
15
+ * Get event name from JS request.
16
+ *
17
+ * @return event name
18
+ */
19
+ - (NSString *)eventName;
20
+
21
+ @end
@@ -0,0 +1,19 @@
1
+ //
2
+ // CDVInvokedUrlCommand+CULPlugin.m
3
+ //
4
+ // Created by Nikolay Demyankov on 08.12.15.
5
+ //
6
+
7
+ #import "CDVInvokedUrlCommand+CULPlugin.h"
8
+
9
+ @implementation CDVInvokedUrlCommand (CULPlugin)
10
+
11
+ - (NSString *)eventName {
12
+ if (self.arguments.count == 0) {
13
+ return nil;
14
+ }
15
+
16
+ return self.arguments[0];
17
+ }
18
+
19
+ @end
@@ -0,0 +1,29 @@
1
+ //
2
+ // CDVPluginResult+CULPlugin.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Cordova/CDVPlugin.h>
8
+ #import "CULHost.h"
9
+
10
+ /**
11
+ * Category to simplify plugin result generation.
12
+ */
13
+ @interface CDVPluginResult (CULPlugin)
14
+
15
+ /**
16
+ * Get CDVPluginResult instance with information about the launch url that is send to JS.
17
+ *
18
+ * @param host host that corresponds to launch url
19
+ * @param originalURL launching url
20
+ *
21
+ * @return instance of the CDVPluginResult
22
+ */
23
+ + (instancetype)resultWithHost:(CULHost *)host originalURL:(NSURL *)originalURL;
24
+
25
+ - (BOOL)isResultForEvent:(NSString *)eventName;
26
+
27
+ - (NSString *)eventName;
28
+
29
+ @end
@@ -0,0 +1,157 @@
1
+ //
2
+ // CDVPluginResult+CULPlugin.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "CDVPluginResult+CULPlugin.h"
8
+
9
+ #pragma mark keys for the message structure
10
+
11
+ // event name
12
+ static NSString *const EVENT = @"event";
13
+
14
+ // message data block
15
+ static NSString *const DATA = @"data";
16
+
17
+ #pragma mark keys for the message data block
18
+
19
+ // path part from the url
20
+ static NSString *const PATH_ATTRIBUTE = @"path";
21
+
22
+ // scheme from the url
23
+ static NSString *const SCHEME_ATTRIBUTE = @"scheme";
24
+
25
+ // host name from the url
26
+ static NSString *const HOST_ATTRIBUTE = @"host";
27
+
28
+ // hash (fragment) from the url; data after '#'
29
+ static NSString *const HASH_ATTRIBUTE = @"hash";
30
+
31
+ // launch url without any changes
32
+ static NSString *const ORIGIN_ATTRIBUTE = @"url";
33
+
34
+ // query parameters from the url; data after '?'
35
+ static NSString *const URL_PARAMS_ATTRIBUTE = @"params";
36
+
37
+ @implementation CDVPluginResult (CULPlugin)
38
+
39
+ #pragma mark Public API
40
+
41
+ + (instancetype)resultWithHost:(CULHost *)host originalURL:(NSURL *)originalURL {
42
+ NSDictionary *message = [self prepareMessageForHost:host originalURL:originalURL];
43
+
44
+ CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message];
45
+ [result setKeepCallbackAsBool:YES];
46
+
47
+ return result;
48
+ }
49
+
50
+ - (BOOL)isResultForEvent:(NSString *)eventName {
51
+ NSString *eventInMessage = [self eventName];
52
+ if (eventInMessage.length == 0 || eventName.length == 0) {
53
+ return NO;
54
+ }
55
+
56
+ return [eventInMessage isEqualToString:eventName];
57
+ }
58
+
59
+ - (NSString *)eventName {
60
+ if (self.message == nil || ![self.message isKindOfClass:[NSDictionary class]]) {
61
+ return nil;
62
+ }
63
+
64
+ NSDictionary *data = self.message;
65
+
66
+ return data[EVENT];
67
+ }
68
+
69
+ #pragma mark Private API
70
+
71
+ /**
72
+ * Create dictionary for message, that should be send to JS.
73
+ * Holds event name and event details.
74
+ *
75
+ * @param host host entry that corresponds to the url
76
+ * @param originalURL launch url
77
+ *
78
+ * @return messasge dictionary
79
+ */
80
+ + (NSDictionary *)prepareMessageForHost:(CULHost *)host originalURL:(NSURL *)originalURL {
81
+ NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:originalURL resolvingAgainstBaseURL:YES];
82
+ NSMutableDictionary *messageDict = [[NSMutableDictionary alloc] init];
83
+
84
+ // set event name
85
+ NSString *eventName = [self getEventNameBasedOnHost:host originalURLComponents:urlComponents];
86
+ [messageDict setObject:eventName forKey:EVENT];
87
+
88
+ // set event details
89
+ NSDictionary *data = [self getDataDictionaryForURLComponents:urlComponents];
90
+ [messageDict setObject:data forKey:DATA];
91
+
92
+ return messageDict;
93
+ }
94
+
95
+ /**
96
+ * Find event name based on the launch url and corresponding host entry.
97
+ *
98
+ * @param host host entry
99
+ * @param urlComponents launch url components
100
+ *
101
+ * @return event name
102
+ */
103
+ + (NSString *)getEventNameBasedOnHost:(CULHost *)host originalURLComponents:(NSURLComponents *)urlComponents {
104
+ NSString *eventName = host.event;
105
+ NSArray<CULPath *> *hostPaths = host.paths;
106
+ NSString *originalPath = urlComponents.path.lowercaseString;
107
+
108
+ if (originalPath.length == 0) {
109
+ return eventName;
110
+ }
111
+
112
+ for (CULPath *hostPath in hostPaths) {
113
+ NSRange range = [originalPath rangeOfString:hostPath.url options:NSRegularExpressionSearch];
114
+ if (range.location != NSNotFound && range.location == 0) {
115
+ eventName = hostPath.event;
116
+ break;
117
+ }
118
+ }
119
+
120
+ return eventName;
121
+ }
122
+
123
+ /**
124
+ * Create dictionary with event details.
125
+ *
126
+ * @param originalURLComponents launch url components
127
+ *
128
+ * @return dictionary with url information
129
+ */
130
+ + (NSDictionary *)getDataDictionaryForURLComponents:(NSURLComponents *)originalURLComponents {
131
+ NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] init];
132
+
133
+ NSString *originUrl = originalURLComponents.URL.absoluteString;
134
+ NSString *host = originalURLComponents.host ? originalURLComponents.host : @"";
135
+ NSString *path = originalURLComponents.path ? originalURLComponents.path : @"";
136
+ NSString *scheme = originalURLComponents.scheme ? originalURLComponents.scheme : @"";
137
+ NSString *hash = originalURLComponents.fragment ? originalURLComponents.fragment : @"";
138
+
139
+ [dataDict setObject:originUrl forKey:ORIGIN_ATTRIBUTE];
140
+ [dataDict setObject:host forKey:HOST_ATTRIBUTE];
141
+ [dataDict setObject:path forKey:PATH_ATTRIBUTE];
142
+ [dataDict setObject:scheme forKey:SCHEME_ATTRIBUTE];
143
+ [dataDict setObject:hash forKey:HASH_ATTRIBUTE];
144
+
145
+ // set query params
146
+ NSArray<NSURLQueryItem *> *queryItems = originalURLComponents.queryItems;
147
+ NSMutableDictionary<NSString *, NSString *> *qParams = [[NSMutableDictionary alloc] init];
148
+ for (NSURLQueryItem *qItem in queryItems) {
149
+ NSString *value = qItem.value ? qItem.value : @"";
150
+ [qParams setValue:value forKey:qItem.name];
151
+ }
152
+ [dataDict setObject:qParams forKey:URL_PARAMS_ATTRIBUTE];
153
+
154
+ return dataDict;
155
+ }
156
+
157
+ @end