@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,63 @@
1
+ //
2
+ // CULHost.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+ #import "CULPath.h"
9
+
10
+ /**
11
+ * Model for <host /> entry, specified in config.xml.
12
+ */
13
+ @interface CULHost : NSObject
14
+
15
+ /**
16
+ * Host name.
17
+ * Defined as 'name' attribute.
18
+ */
19
+ @property (nonatomic, readonly, strong) NSString *name;
20
+
21
+ /**
22
+ * Host scheme.
23
+ * Defined as 'scheme' attribute.
24
+ */
25
+ @property (nonatomic, readonly, strong) NSString *scheme;
26
+
27
+ /**
28
+ * Event name that is sent to JS when user clicks on the link from this host.
29
+ * Defined as 'event' attribute.
30
+ */
31
+ @property (nonatomic, strong) NSString *event;
32
+
33
+ /**
34
+ * List of paths, that is set for that host in config.xml.
35
+ */
36
+ @property (nonatomic, readonly, strong) NSArray<CULPath *> *paths;
37
+
38
+ /**
39
+ * Constructor.
40
+ *
41
+ * @param name host name
42
+ * @param scheme scheme; if <code>nil</code> - http will be used
43
+ * @param event event name; if <code>nil</code> - didLaunchAppFromLink event name will be used
44
+ *
45
+ * @return instance of the CULHost
46
+ */
47
+ - (instancetype)initWithHostName:(NSString *)name scheme:(NSString *)scheme event:(NSString *)event;
48
+
49
+ /**
50
+ * Add path entry to the host paths list.
51
+ *
52
+ * @param path path to add
53
+ */
54
+ - (void)addPath:(CULPath *)path;
55
+
56
+ /**
57
+ * Add list of paths.
58
+ *
59
+ * @param paths paths to add
60
+ */
61
+ - (void)addAllPaths:(NSArray<CULPath *> *)paths;
62
+
63
+ @end
@@ -0,0 +1,50 @@
1
+ //
2
+ // CULHost.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "CULHost.h"
8
+
9
+ // default event name
10
+ static NSString *const DEFAULT_EVENT = @"didLaunchAppFromLink";
11
+
12
+ // default host scheme
13
+ static NSString *const DEFAULT_SCHEME = @"http";
14
+
15
+ @interface CULHost() {
16
+ NSMutableArray<CULPath *> *_paths;
17
+ }
18
+
19
+ @end
20
+
21
+ @implementation CULHost
22
+
23
+ - (instancetype)initWithHostName:(NSString *)name scheme:(NSString *)scheme event:(NSString *)event {
24
+ self = [super init];
25
+ if (self) {
26
+ _event = event ? event : DEFAULT_EVENT;
27
+ _scheme = scheme ? scheme : DEFAULT_SCHEME;
28
+ _name = name.lowercaseString;
29
+ _paths = [[NSMutableArray alloc] init];
30
+ }
31
+ return self;
32
+ }
33
+
34
+ - (void)addPath:(CULPath *)path {
35
+ if (path) {
36
+ [_paths addObject:path];
37
+ }
38
+ }
39
+
40
+ - (void)addAllPaths:(NSArray<CULPath *> *)paths {
41
+ if (paths) {
42
+ [_paths addObjectsFromArray:paths];
43
+ }
44
+ }
45
+
46
+ - (NSArray<CULPath *> *)paths {
47
+ return _paths;
48
+ }
49
+
50
+ @end
@@ -0,0 +1,36 @@
1
+ //
2
+ // CULPath.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+
9
+ /**
10
+ * Model for <path /> entry for host in config.xml.
11
+ */
12
+ @interface CULPath : NSObject
13
+
14
+ /**
15
+ * Event name that is dispatched when application is launched from the link with this path.
16
+ * Defined as 'event' attribute.
17
+ */
18
+ @property (nonatomic, readonly, strong) NSString *event;
19
+
20
+ /**
21
+ * Path url.
22
+ * Defined as 'url' attribute.
23
+ */
24
+ @property (nonatomic, readonly, strong) NSString *url;
25
+
26
+ /**
27
+ * Constructor
28
+ *
29
+ * @param urlPath url path
30
+ * @param event event name
31
+ *
32
+ * @return instance of the CULPath
33
+ */
34
+ - (instancetype)initWithUrlPath:(NSString *)urlPath andEvent:(NSString *)event;
35
+
36
+ @end
@@ -0,0 +1,21 @@
1
+ //
2
+ // CULPath.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "CULPath.h"
8
+
9
+ @implementation CULPath
10
+
11
+ - (instancetype)initWithUrlPath:(NSString *)urlPath andEvent:(NSString *)event {
12
+ self = [super init];
13
+ if (self) {
14
+ _url = [urlPath stringByReplacingOccurrencesOfString:@"*" withString:@".*"].lowercaseString;
15
+ _event = event;
16
+ }
17
+
18
+ return self;
19
+ }
20
+
21
+ @end
@@ -0,0 +1,22 @@
1
+ //
2
+ // CULConfigJsonParser.h
3
+ //
4
+ // Created by Nikolay Demyankov on 29.01.17.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+ #import "CULHost.h"
9
+
10
+ /**
11
+ * JSON parser for plugin's preferences.
12
+ */
13
+ @interface CULConfigJsonParser : NSObject
14
+
15
+ /**
16
+ * Parse JSON config.
17
+ *
18
+ * @return list of hosts, defined in the config file
19
+ */
20
+ + (NSArray<CULHost *> *)parseConfig:(NSString *)pathToJsonConfig;
21
+
22
+ @end
@@ -0,0 +1,60 @@
1
+ //
2
+ // CULConfigJsonParser.m
3
+ //
4
+ // Created by Nikolay Demyankov on 29.01.17.
5
+ //
6
+
7
+ #import "CULConfigJsonParser.h"
8
+
9
+ @implementation CULConfigJsonParser
10
+
11
+ + (NSArray<CULHost *> *)parseConfig:(NSString *)pathToJsonConfig {
12
+ NSData *ulData = [NSData dataWithContentsOfFile:pathToJsonConfig];
13
+ if (!ulData) {
14
+ return nil;
15
+ }
16
+
17
+ NSError *error = nil;
18
+ NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:ulData options:kNilOptions error:&error];
19
+ if (error) {
20
+ return nil;
21
+ }
22
+
23
+ NSMutableArray<CULHost *> *preferences = [[NSMutableArray alloc] init];
24
+ for (NSDictionary *jsonEntry in jsonObject) {
25
+ CULHost *host = [[CULHost alloc] initWithHostName:jsonEntry[@"host"]
26
+ scheme:jsonEntry[@"scheme"]
27
+ event:jsonEntry[@"event"]];
28
+ NSArray<CULPath *> *paths = [self parsePathsFromJson:jsonEntry[@"path"] forHost:host];
29
+ [host addAllPaths:paths];
30
+
31
+ [preferences addObject:host];
32
+ }
33
+
34
+ return preferences;
35
+ }
36
+
37
+ + (NSArray<CULPath *> *)parsePathsFromJson:(NSArray *)jsonArray forHost:(CULHost *)host {
38
+ if (!jsonArray || !jsonArray.count) {
39
+ return nil;
40
+ }
41
+
42
+ NSMutableArray<CULPath *> *paths = [[NSMutableArray alloc] initWithCapacity:jsonArray.count];
43
+ for (NSDictionary *entry in jsonArray) {
44
+ NSString *urlPath = entry[@"url"];
45
+ NSString *pathEvent = entry[@"event"] ? entry[@"event"] : host.event;
46
+
47
+ // ignore '*' paths; we don't need them here
48
+ if ([urlPath isEqualToString:@"*"] || [urlPath isEqualToString:@".*"]) {
49
+ continue;
50
+ }
51
+
52
+ // create path entry
53
+ CULPath *path = [[CULPath alloc] initWithUrlPath:urlPath andEvent:pathEvent];
54
+ [paths addObject:path];
55
+ }
56
+
57
+ return paths;
58
+ }
59
+
60
+ @end
@@ -0,0 +1,22 @@
1
+ //
2
+ // CULConfigXmlParser.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+ #import "CULHost.h"
9
+
10
+ /**
11
+ * Parser for config.xml. Reads only plugin-specific preferences.
12
+ */
13
+ @interface CULConfigXmlParser : NSObject
14
+
15
+ /**
16
+ * Parse config.xml
17
+ *
18
+ * @return list of hosts, defined in the config file
19
+ */
20
+ + (NSArray<CULHost *> *)parse;
21
+
22
+ @end
@@ -0,0 +1,123 @@
1
+ //
2
+ // CULConfigXmlParser.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "CULConfigXmlParser.h"
8
+ #import "NSBundle+CULPlugin.h"
9
+ #import "CULPath.h"
10
+ #import "CULXmlTags.h"
11
+
12
+ @interface CULConfigXmlParser() <NSXMLParserDelegate> {
13
+ NSMutableArray<CULHost *> *_hostsList;
14
+ BOOL _isInsideMainTag;
15
+ BOOL _didParseMainBlock;
16
+ BOOL _isInsideHostBlock;
17
+ CULHost *_processedHost;
18
+ }
19
+
20
+ @end
21
+
22
+ @implementation CULConfigXmlParser
23
+
24
+ #pragma mark Public API
25
+
26
+ + (NSArray<CULHost *> *)parse {
27
+ CULConfigXmlParser *parser = [[CULConfigXmlParser alloc] init];
28
+
29
+ return [parser parseConfig];
30
+ }
31
+
32
+ - (NSArray<CULHost *> *)parseConfig {
33
+ NSURL *cordovaConfigURL = [NSURL fileURLWithPath:[NSBundle pathToCordovaConfigXml]];
34
+ NSXMLParser *configParser = [[NSXMLParser alloc] initWithContentsOfURL:cordovaConfigURL];
35
+ if (configParser == nil) {
36
+ NSLog(@"Failed to initialize XML parser.");
37
+ return nil;
38
+ }
39
+
40
+ _hostsList = [[NSMutableArray alloc] init];
41
+ [configParser setDelegate:self];
42
+ [configParser parse];
43
+
44
+ return _hostsList;
45
+ }
46
+
47
+ #pragma mark NSXMLParserDelegate implementation
48
+
49
+ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
50
+ if (_didParseMainBlock) {
51
+ return;
52
+ }
53
+
54
+ if ([elementName isEqualToString:kCULMainXmlTag]) {
55
+ _isInsideMainTag = YES;
56
+ return;
57
+ }
58
+ if (!_isInsideMainTag) {
59
+ return;
60
+ }
61
+
62
+ if ([elementName isEqualToString:kCULHostXmlTag]) {
63
+ [self processHostTag:attributeDict];
64
+ } else if ([elementName isEqualToString:kCULPathXmlTag]) {
65
+ [self processPathTag:attributeDict];
66
+ }
67
+ }
68
+
69
+ - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
70
+ if (_didParseMainBlock || !_isInsideMainTag) {
71
+ return;
72
+ }
73
+
74
+ if ([elementName isEqualToString:kCULHostXmlTag]) {
75
+ _isInsideHostBlock = NO;
76
+ [_hostsList addObject:_processedHost];
77
+ }
78
+ }
79
+
80
+ #pragma mark XML Processing
81
+
82
+ /**
83
+ * Parse host tag.
84
+ *
85
+ * @param attributes host tag attributes
86
+ */
87
+ - (void)processHostTag:(NSDictionary<NSString *, NSString *> *)attributes {
88
+ _processedHost = [[CULHost alloc] initWithHostName:attributes[kCULHostNameXmlAttribute]
89
+ scheme:attributes[kCULHostSchemeXmlAttribute]
90
+ event:attributes[kCULHostEventXmlAttribute]];
91
+ _isInsideHostBlock = YES;
92
+ }
93
+
94
+ /**
95
+ * Parse path tag.
96
+ *
97
+ * @param attributes path tag attributes
98
+ */
99
+ - (void)processPathTag:(NSDictionary<NSString *, NSString *> *)attributes {
100
+ NSString *urlPath = attributes[kCULPathUrlXmlAttribute];
101
+ NSString *event = attributes[kCULPathEventXmlAttribute];
102
+
103
+ // ignore '*' paths; we don't need them here
104
+ if ([urlPath isEqualToString:@"*"] || [urlPath isEqualToString:@".*"]) {
105
+ // but if path has event name - set it to host
106
+ if (event) {
107
+ _processedHost.event = event;
108
+ }
109
+
110
+ return;
111
+ }
112
+
113
+ // if event name is empty - use one from the host
114
+ if (event == nil) {
115
+ event = _processedHost.event;
116
+ }
117
+
118
+ // create path entry
119
+ CULPath *path = [[CULPath alloc] initWithUrlPath:urlPath andEvent:event];
120
+ [_processedHost addPath:path];
121
+ }
122
+
123
+ @end
@@ -0,0 +1,54 @@
1
+ //
2
+ // CULXmlTags.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+
9
+ /**
10
+ * XML tags that is used in config.xml to specify plugin preferences.
11
+ */
12
+ @interface CULXmlTags : NSObject
13
+
14
+ /**
15
+ * Main tag in which we define plugin related stuff
16
+ */
17
+ extern NSString *const kCULMainXmlTag;
18
+
19
+ /**
20
+ * Host main tag
21
+ */
22
+ extern NSString *const kCULHostXmlTag;
23
+
24
+ /**
25
+ * Scheme attribute for the host entry
26
+ */
27
+ extern NSString *const kCULHostSchemeXmlAttribute;
28
+
29
+ /**
30
+ * Name attribute for the host entry
31
+ */
32
+ extern NSString *const kCULHostNameXmlAttribute;
33
+
34
+ /**
35
+ * Event attribute for the host entry
36
+ */
37
+ extern NSString *const kCULHostEventXmlAttribute;
38
+
39
+ /**
40
+ * Path main tag
41
+ */
42
+ extern NSString *const kCULPathXmlTag;
43
+
44
+ /**
45
+ * Url attribute for the path entry
46
+ */
47
+ extern NSString *const kCULPathUrlXmlAttribute;
48
+
49
+ /**
50
+ * Event attribute for the path entry
51
+ */
52
+ extern NSString *const kCULPathEventXmlAttribute;
53
+
54
+ @end
@@ -0,0 +1,22 @@
1
+ //
2
+ // CULXmlTags.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "CULXmlTags.h"
8
+
9
+ @implementation CULXmlTags
10
+
11
+ NSString *const kCULMainXmlTag = @"universal-links";
12
+
13
+ NSString *const kCULHostXmlTag = @"host";
14
+ NSString *const kCULHostSchemeXmlAttribute = @"scheme";
15
+ NSString *const kCULHostNameXmlAttribute = @"name";
16
+ NSString *const kCULHostEventXmlAttribute = @"event";
17
+
18
+ NSString *const kCULPathXmlTag = @"path";
19
+ NSString *const kCULPathUrlXmlAttribute = @"url";
20
+ NSString *const kCULPathEventXmlAttribute = @"event";
21
+
22
+ @end
@@ -0,0 +1,22 @@
1
+ //
2
+ // NSBundle+CULPlugin.h
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+
9
+ /**
10
+ * Helper category to work with NSBundle.
11
+ */
12
+ @interface NSBundle (CULPlugin)
13
+
14
+ /**
15
+ * Path to the config.xml file in the project.
16
+ *
17
+ * @return path to the config file
18
+ */
19
+ + (NSString *)pathToCordovaConfigXml;
20
+
21
+
22
+ @end
@@ -0,0 +1,15 @@
1
+ //
2
+ // NSBundle+CULPlugin.m
3
+ //
4
+ // Created by Nikolay Demyankov on 15.09.15.
5
+ //
6
+
7
+ #import "NSBundle+CULPlugin.h"
8
+
9
+ @implementation NSBundle (CULPlugin)
10
+
11
+ + (NSString *)pathToCordovaConfigXml {
12
+ return [[NSBundle mainBundle] pathForResource:@"config" ofType:@"xml"];
13
+ }
14
+
15
+ @end
@@ -0,0 +1,23 @@
1
+ <!--
2
+ Besides activating Deep Links in the application - you need to enable indexing for your web pages.
3
+ For that you should add <link /> tags in the <head> section of the web pages that you specified in config.xml.
4
+ Doing so, you declare that this page should be openned in the mobile application instead of the browser.
5
+
6
+ Link tag is look like this:
7
+ <link rel="alternate" href="android-app://<package_name>/<scheme>/<host>/<path>" />
8
+
9
+ More documentation could be found here:
10
+ https://developer.android.com/training/app-indexing/enabling-app-indexing.html
11
+
12
+ For convenience, plugin generates the list of <link /> tags based on what you specified in the config.xml.
13
+ You can just copy-paste them in the <header> section of the appropriate pages of your website.
14
+
15
+ -->
16
+
17
+ <head>
18
+ [__LINKS__]
19
+ <!-- Your other stuff from the head tag -->
20
+ </head>
21
+ <body>
22
+ <!-- Your page content -->
23
+ </body>
@@ -0,0 +1,56 @@
1
+ var exec = require('cordova/exec'),
2
+ channel = require('cordova/channel'),
3
+
4
+ // Reference name for the plugin
5
+ PLUGIN_NAME = 'UniversalLinks',
6
+
7
+ // Default event name that is used by the plugin
8
+ DEFAULT_EVENT_NAME = 'didLaunchAppFromLink';
9
+
10
+ // Plugin methods on the native side that can be called from JavaScript
11
+ pluginNativeMethod = {
12
+ SUBSCRIBE: 'jsSubscribeForEvent',
13
+ UNSUBSCRIBE: 'jsUnsubscribeFromEvent'
14
+ };
15
+
16
+ var universalLinks = {
17
+
18
+ /**
19
+ * Subscribe to event.
20
+ * If plugin already captured that event - callback will be called immidietly.
21
+ *
22
+ * @param {String} eventName - name of the event you are subscribing on; if null - default plugin event is used
23
+ * @param {Function} callback - callback that is called when event is captured
24
+ */
25
+ subscribe: function(eventName, callback) {
26
+ if (!callback) {
27
+ console.warn('Universal Links: can\'t subscribe to event without a callback');
28
+ return;
29
+ }
30
+
31
+ if (!eventName) {
32
+ eventName = DEFAULT_EVENT_NAME;
33
+ }
34
+
35
+ var innerCallback = function(msg) {
36
+ callback(msg.data);
37
+ };
38
+
39
+ exec(innerCallback, null, PLUGIN_NAME, pluginNativeMethod.SUBSCRIBE, [eventName]);
40
+ },
41
+
42
+ /**
43
+ * Unsubscribe from the event.
44
+ *
45
+ * @param {String} eventName - from what event we are unsubscribing
46
+ */
47
+ unsubscribe: function(eventName) {
48
+ if (!eventName) {
49
+ eventName = DEFAULT_EVENT_NAME;
50
+ }
51
+
52
+ exec(null, null, PLUGIN_NAME, pluginNativeMethod.UNSUBSCRIBE, [eventName]);
53
+ }
54
+ };
55
+
56
+ module.exports = universalLinks;