-
Notifications
You must be signed in to change notification settings - Fork 576
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Conrad Kramer
committed
Feb 26, 2015
1 parent
35f21ff
commit 8ef8f53
Showing
8 changed files
with
387 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Copyright (c) 2014, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
*/ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
#import "BFAppLinkResolving.h" | ||
#import "BFAppLinkResolvingPrivate.h" | ||
#import "BFAppLink.h" | ||
#import "BFAppLinkTarget.h" | ||
|
||
NSString *const BFAppLinkResolverPreferHeader = @"Prefer-Html-Meta-Tags"; | ||
NSString *const BFAppLinkResolverMetaTagPrefix = @"al"; | ||
|
||
static NSString *const BFAppLinkResolverIOSURLKey = @"url"; | ||
static NSString *const BFAppLinkResolverIOSAppStoreIdKey = @"app_store_id"; | ||
static NSString *const BFAppLinkResolverIOSAppNameKey = @"app_name"; | ||
static NSString *const BFAppLinkResolverDictionaryValueKey = @"_value"; | ||
static NSString *const BFAppLinkResolverWebKey = @"web"; | ||
static NSString *const BFAppLinkResolverIOSKey = @"ios"; | ||
static NSString *const BFAppLinkResolverIPhoneKey = @"iphone"; | ||
static NSString *const BFAppLinkResolverIPadKey = @"ipad"; | ||
static NSString *const BFAppLinkResolverWebURLKey = @"url"; | ||
static NSString *const BFAppLinkResolverShouldFallbackKey = @"should_fallback"; | ||
|
||
NSDictionary *BFAppLinkResolverParseALData(NSArray *dataArray) { | ||
NSMutableDictionary *al = [NSMutableDictionary dictionary]; | ||
for (NSDictionary *tag in dataArray) { | ||
NSString *name = tag[@"property"]; | ||
if (![name isKindOfClass:[NSString class]]) { | ||
continue; | ||
} | ||
NSArray *nameComponents = [name componentsSeparatedByString:@":"]; | ||
if (![nameComponents[0] isEqualToString:BFAppLinkResolverMetaTagPrefix]) { | ||
continue; | ||
} | ||
NSMutableDictionary *root = al; | ||
for (int i = 1; i < nameComponents.count; i++) { | ||
NSMutableArray *children = root[nameComponents[i]]; | ||
if (!children) { | ||
children = [NSMutableArray array]; | ||
root[nameComponents[i]] = children; | ||
} | ||
NSMutableDictionary *child = children.lastObject; | ||
if (!child || i == nameComponents.count - 1) { | ||
child = [NSMutableDictionary dictionary]; | ||
[children addObject:child]; | ||
} | ||
root = child; | ||
} | ||
if (tag[@"content"]) { | ||
root[BFAppLinkResolverDictionaryValueKey] = tag[@"content"]; | ||
} | ||
} | ||
return al; | ||
} | ||
|
||
BFAppLink *BFAppLinkResolverAppLinkFromALData(NSDictionary *appLinkDict, NSURL *destination) { | ||
NSMutableArray *linkTargets = [NSMutableArray array]; | ||
|
||
NSArray *platformData = nil; | ||
switch (UI_USER_INTERFACE_IDIOM()) { | ||
case UIUserInterfaceIdiomPad: | ||
platformData = @[appLinkDict[BFAppLinkResolverIPadKey] ?: @{}, | ||
appLinkDict[BFAppLinkResolverIOSKey] ?: @{}]; | ||
break; | ||
case UIUserInterfaceIdiomPhone: | ||
platformData = @[appLinkDict[BFAppLinkResolverIPhoneKey] ?: @{}, | ||
appLinkDict[BFAppLinkResolverIOSKey] ?: @{}]; | ||
break; | ||
default: | ||
// Future-proofing. Other User Interface idioms should only hit ios. | ||
platformData = @[appLinkDict[BFAppLinkResolverIOSKey] ?: @{}]; | ||
break; | ||
} | ||
|
||
for (NSArray *platformObjects in platformData) { | ||
for (NSDictionary *platformDict in platformObjects) { | ||
// The schema requires a single url/app store id/app name, | ||
// but we could find multiple of them. We'll make a best effort | ||
// to interpret this data. | ||
NSArray *urls = platformDict[BFAppLinkResolverIOSURLKey]; | ||
NSArray *appStoreIds = platformDict[BFAppLinkResolverIOSAppStoreIdKey]; | ||
NSArray *appNames = platformDict[BFAppLinkResolverIOSAppNameKey]; | ||
|
||
NSUInteger maxCount = MAX(urls.count, MAX(appStoreIds.count, appNames.count)); | ||
|
||
for (NSUInteger i = 0; i < maxCount; i++) { | ||
NSString *urlString = urls[i][BFAppLinkResolverDictionaryValueKey]; | ||
NSURL *url = urlString ? [NSURL URLWithString:urlString] : nil; | ||
NSString *appStoreId = appStoreIds[i][BFAppLinkResolverDictionaryValueKey]; | ||
NSString *appName = appNames[i][BFAppLinkResolverDictionaryValueKey]; | ||
BFAppLinkTarget *target = [BFAppLinkTarget appLinkTargetWithURL:url | ||
appStoreId:appStoreId | ||
appName:appName]; | ||
[linkTargets addObject:target]; | ||
} | ||
} | ||
} | ||
|
||
NSDictionary *webDict = appLinkDict[BFAppLinkResolverWebKey][0]; | ||
NSString *webUrlString = webDict[BFAppLinkResolverWebURLKey][0][BFAppLinkResolverDictionaryValueKey]; | ||
NSString *shouldFallbackString = webDict[BFAppLinkResolverShouldFallbackKey][0][BFAppLinkResolverDictionaryValueKey]; | ||
|
||
NSURL *webUrl = destination; | ||
|
||
if (shouldFallbackString && | ||
[@[@"no", @"false", @"0"] containsObject:[shouldFallbackString lowercaseString]]) { | ||
webUrl = nil; | ||
} | ||
if (webUrl && webUrlString) { | ||
webUrl = [NSURL URLWithString:webUrlString]; | ||
} | ||
|
||
return [BFAppLink appLinkWithSourceURL:destination | ||
targets:linkTargets | ||
webURL:webUrl]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright (c) 2014, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
*/ | ||
|
||
@class BFAppLink; | ||
|
||
/* | ||
Builds up a data structure filled with the app link data from the meta tags on a page. | ||
The structure of this object is a dictionary where each key holds an array of app link | ||
data dictionaries. Values are stored in a key called "_value". | ||
*/ | ||
extern NSDictionary *BFAppLinkResolverParseALData(NSArray *dataArray); | ||
|
||
/* | ||
Converts app link data into a BFAppLink containing the targets relevant for this platform. | ||
*/ | ||
extern BFAppLink *BFAppLinkResolverAppLinkFromALData(NSDictionary *appLinkDict, NSURL *destination); | ||
|
||
extern NSString *const BFAppLinkResolverPreferHeader; | ||
extern NSString *const BFAppLinkResolverMetaTagPrefix; |
Oops, something went wrong.