Added RCTBundleURLProvider

Reviewed By: javache

Differential Revision: D3352568

fbshipit-source-id: fbba6771a1c581e2676bd0f81d3da62dbf21916b
This commit is contained in:
Nathan Azaria
2016-05-31 04:56:49 -07:00
committed by Facebook Github Bot 6
parent c2c370c886
commit 3ccd99fb53
5 changed files with 318 additions and 0 deletions

View File

@@ -63,6 +63,7 @@
27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; };
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
3DB99D0C1BA0340600302749 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */; };
68FF44381CF6111500720EFD /* RCTBundleURLProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FF44371CF6111500720EFD /* RCTBundleURLProviderTests.m */; };
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8385CEF41B873B5C00C6273E /* RCTImageLoaderTests.m */; };
@@ -248,6 +249,7 @@
357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = "<group>"; };
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
68FF44371CF6111500720EFD /* RCTBundleURLProviderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBundleURLProviderTests.m; sourceTree = "<group>"; };
83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
8385CEF41B873B5C00C6273E /* RCTImageLoaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageLoaderTests.m; sourceTree = "<group>"; };
8385CF031B87479200C6273E /* RCTImageLoaderHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageLoaderHelpers.m; sourceTree = "<group>"; };
@@ -415,6 +417,7 @@
isa = PBXGroup;
children = (
13B6C1A21C34225900D3FAF5 /* RCTURLUtilsTests.m */,
68FF44371CF6111500720EFD /* RCTBundleURLProviderTests.m */,
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */,
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */,
1497CFA61B21F5E400C1F8F2 /* RCTJSCExecutorTests.m */,
@@ -903,6 +906,7 @@
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */,
13B6C1A31C34225900D3FAF5 /* RCTURLUtilsTests.m in Sources */,
8385CF041B87479200C6273E /* RCTImageLoaderHelpers.m in Sources */,
68FF44381CF6111500720EFD /* RCTBundleURLProviderTests.m in Sources */,
8385CEF51B873B5C00C6273E /* RCTImageLoaderTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@@ -0,0 +1,103 @@
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <XCTest/XCTest.h>
#import "RCTBundleURLProvider.h"
#import "RCTUtils.h"
static NSString *const testFile = @"test.jsbundle";
static NSString *const mainBundle = @"main.jsbundle";
static NSURL *mainBundleURL()
{
return [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:mainBundle];
}
static NSURL *localhostBundleURL()
{
return [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false", testFile]];
}
static NSURL *ipBundleURL()
{
return [NSURL URLWithString:[NSString stringWithFormat:@"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false", testFile]];
}
@implementation NSBundle (RCTBundleURLProviderTests)
- (NSURL *)RCT_URLForResource:(NSString *)name withExtension:(NSString *)ext
{
// Ensure that test files is always reported as existing
if ([[name stringByAppendingFormat:@".%@", ext] isEqualToString:mainBundle]) {
return [[self bundleURL] URLByAppendingPathComponent:mainBundle];
}
return [self RCT_URLForResource:name withExtension:ext];
}
@end
@interface RCTBundleURLProviderTests : XCTestCase
@end
@implementation RCTBundleURLProviderTests
- (void)setUp
{
[super setUp];
RCTSwapInstanceMethods([NSBundle class],
@selector(URLForResource:withExtension:),
@selector(RCT_URLForResource:withExtension:));
[[RCTBundleURLProvider sharedSettings] setDefaults];
}
- (void)tearDown
{
RCTSwapInstanceMethods([NSBundle class],
@selector(URLForResource:withExtension:),
@selector(RCT_URLForResource:withExtension:));
[super tearDown];
}
- (void)testBundleURL
{
RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
settings.jsLocation = nil;
NSURL *URL = [settings jsBundleURLForBundleRoot:testFile fallbackResource:nil];
if (!getenv("CI_USE_PACKAGER")) {
XCTAssertEqualObjects(URL, mainBundleURL());
} else {
XCTAssertEqualObjects(URL, localhostBundleURL());
}
}
- (void)testLocalhostURL
{
RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
settings.jsLocation = @"localhost";
NSURL *URL = [settings jsBundleURLForBundleRoot:testFile fallbackResource:nil];
XCTAssertEqualObjects(URL, localhostBundleURL());
}
- (void)testIPURL
{
RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
settings.jsLocation = @"192.168.1.1";
NSURL *URL = [settings jsBundleURLForBundleRoot:testFile fallbackResource:nil];
XCTAssertEqualObjects(URL, ipBundleURL());
}
@end

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-present, 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 <Foundation/Foundation.h>
@interface RCTBundleURLProvider : NSObject
extern NSString *const RCTBundleURLProviderUpdatedNotification;
/**
* Set default settings on NSUserDefaults.
*/
- (void)setDefaults;
/**
* Returns the jsBundleURL for a given bundle entrypoint and
* the fallback offline JS bundle if the packager is not running.
*/
- (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
fallbackResource:(NSString *)resourceName;
/**
* The IP address or hostname of the packager.
*/
@property (nonatomic, copy) NSString *jsLocation;
@property (nonatomic, assign) BOOL enableLiveReload;
@property (nonatomic, assign) BOOL enableMinification;
@property (nonatomic, assign) BOOL enableDev;
+ (instancetype)sharedSettings;
@end

View File

@@ -0,0 +1,167 @@
/**
* Copyright (c) 2015-present, 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 "RCTBundleURLProvider.h"
#import "RCTDefines.h"
#import "RCTConvert.h"
NSString *const RCTBundleURLProviderUpdatedNotification = @"RCTBundleURLProviderUpdatedNotification";
static NSString *const kRCTJsLocationKey = @"RCT_jsLocation";
static NSString *const kRCTEnableLiveReloadKey = @"RCT_enableLiveReload";
static NSString *const kRCTEnableDevKey = @"RCT_enableDev";
static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification";
static NSString *const kDefaultPort = @"8081";
@implementation RCTBundleURLProvider
- (NSDictionary *)defaults
{
static NSDictionary *defaults;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defaults = @{
kRCTEnableLiveReloadKey: @NO,
kRCTEnableDevKey: @YES,
kRCTEnableMinificationKey: @NO,
};
});
return defaults;
}
- (void)settingsUpdated
{
[[NSNotificationCenter defaultCenter] postNotificationName:RCTBundleURLProviderUpdatedNotification object:self];
}
- (void)setDefaults
{
[[NSUserDefaults standardUserDefaults] registerDefaults:[self defaults]];
[self settingsUpdated];
}
- (BOOL)isPackagerRunning:(NSString *)host
{
if (RCT_DEV) {
NSURL *url = [[NSURL URLWithString:serverRootWithHost(host)] URLByAppendingPathComponent:@"status"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
NSString *status = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return [status isEqualToString:@"packager-status:running"];
}
return NO;
}
static NSString *serverRootWithHost(NSString *host)
{
return [NSString stringWithFormat:@"http://%@:%@/", host, kDefaultPort];
}
- (NSString *)guessPackagerHost
{
NSString *host = @"localhost";
//TODO: Implement automatic IP address detection
if ([self isPackagerRunning:host]) {
return host;
}
return nil;
}
- (NSString *)packagerServerRoot
{
NSString *location = [self jsLocation];
if (location != nil) {
return serverRootWithHost(location);
} else {
NSString *host = [self guessPackagerHost];
if (!host) {
return nil;
} else {
return serverRootWithHost(host);
}
}
}
- (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackResource:(NSString *)resourceName
{
resourceName = resourceName ?: @"main";
NSString *serverRoot = [self packagerServerRoot];
if (!serverRoot) {
return [[NSBundle mainBundle] URLForResource:resourceName withExtension:@"jsbundle"];
} else {
NSString *fullBundlePath = [serverRoot stringByAppendingFormat:@"%@.bundle", bundleRoot];
if ([fullBundlePath hasPrefix:@"http"]) {
NSString *dev = [self enableDev] ? @"true" : @"false";
NSString *min = [self enableMinification] ? @"true": @"false";
fullBundlePath = [fullBundlePath stringByAppendingFormat:@"?platform=ios&dev=%@&minify=%@", dev, min];
}
return [NSURL URLWithString:fullBundlePath];
}
}
- (void)updateDefaults:(id)object forKey:(NSString *)key
{
[[NSUserDefaults standardUserDefaults] setObject:object forKey:key];
[[NSUserDefaults standardUserDefaults] synchronize];
[self settingsUpdated];
}
- (BOOL)enableDev
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableDevKey];
}
- (BOOL)enableLiveReload
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableLiveReloadKey];
}
- (BOOL)enableMinification
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableMinificationKey];
}
- (NSString *)jsLocation
{
return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey];
}
- (void)setEnableDev:(BOOL)enableDev
{
[self updateDefaults:@(enableDev) forKey:kRCTEnableDevKey];
}
- (void)setEnableEnableLiveReload:(BOOL)enableLiveReload
{
[self updateDefaults:@(enableLiveReload) forKey:kRCTEnableLiveReloadKey];
}
- (void)setJsLocation:(NSString *)jsLocation
{
[self updateDefaults:jsLocation forKey:kRCTJsLocationKey];
}
- (void)setEnableMinification:(BOOL)enableMinification
{
[self updateDefaults:@(enableMinification) forKey:kRCTEnableMinificationKey];
}
+ (instancetype)sharedSettings
{
static RCTBundleURLProvider *sharedInstance;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
sharedInstance = [RCTBundleURLProvider new];
});
return sharedInstance;
}
@end

View File

@@ -81,6 +81,7 @@
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; };
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */; };
68EFE4EE1CF6EB3900A1DE13 /* RCTBundleURLProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */; };
830A229E1A66C68A008503DA /* RCTRootView.m in Sources */ = {isa = PBXBuildFile; fileRef = 830A229D1A66C68A008503DA /* RCTRootView.m */; };
832348161A77A5AA00B55238 /* Layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FC71A68125100A75B9A /* Layout.c */; };
83392EB31B6634E10013B15F /* RCTModalHostViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83392EB21B6634E10013B15F /* RCTModalHostViewController.m */; };
@@ -272,6 +273,8 @@
58114A4F1AAE93D500E7D092 /* RCTAsyncLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAsyncLocalStorage.h; sourceTree = "<group>"; };
58C571BF1AA56C1900CDF9C8 /* RCTDatePickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDatePickerManager.m; sourceTree = "<group>"; };
58C571C01AA56C1900CDF9C8 /* RCTDatePickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDatePickerManager.h; sourceTree = "<group>"; };
68EFE4EC1CF6EB3000A1DE13 /* RCTBundleURLProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBundleURLProvider.h; sourceTree = "<group>"; };
68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBundleURLProvider.m; sourceTree = "<group>"; };
6A15FB0C1BDF663500531DFB /* RCTRootViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootViewInternal.h; sourceTree = "<group>"; };
830213F31A654E0800B993E6 /* RCTBridgeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeModule.h; sourceTree = "<group>"; };
830A229C1A66C68A008503DA /* RCTRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootView.h; sourceTree = "<group>"; };
@@ -528,6 +531,8 @@
83CBBA491A601E3B00E9B192 /* Base */ = {
isa = PBXGroup;
children = (
68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */,
68EFE4EC1CF6EB3000A1DE13 /* RCTBundleURLProvider.h */,
83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */,
83CBBA4B1A601E3B00E9B192 /* RCTAssert.m */,
14C2CA771B3ACB0400E6CBB2 /* RCTBatchedBridge.m */,
@@ -746,6 +751,7 @@
131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */,
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */,
191E3EBE1C29D9AF00C180A6 /* RCTRefreshControlManager.m in Sources */,
68EFE4EE1CF6EB3900A1DE13 /* RCTBundleURLProvider.m in Sources */,
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
137327E71AA5CF210034F82E /* RCTTabBar.m in Sources */,
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */,