mirror of
https://github.com/zhigang1992/react-native-code-push.git
synced 2026-05-14 02:14:52 +08:00
feedback
This commit is contained in:
34
CodePush.js
34
CodePush.js
@@ -40,9 +40,16 @@ async function checkForUpdate(deploymentKey = null) {
|
||||
* to send the app version to the server, since we are interested
|
||||
* in any updates for current app store version, regardless of hash.
|
||||
*/
|
||||
const queryPackage = localPackage && localPackage.appVersion && semver.compare(localPackage.appVersion, config.appVersion) === 0
|
||||
? localPackage
|
||||
: { appVersion: config.appVersion };
|
||||
const queryPackage;
|
||||
if (localPackage && localPackage.appVersion && semver.compare(localPackage.appVersion, config.appVersion) === 0) {
|
||||
queryPackage = localPackage;
|
||||
} else {
|
||||
queryPackage = { appVersion: config.appVersion };
|
||||
if (Platform.OS === "ios" && config.packageHash) {
|
||||
queryPackage.packageHash = config.packageHash;
|
||||
}
|
||||
}
|
||||
|
||||
const update = await sdk.queryUpdateWithCurrentPackage(queryPackage);
|
||||
|
||||
/*
|
||||
@@ -57,26 +64,19 @@ async function checkForUpdate(deploymentKey = null) {
|
||||
* the currently running update. This should _never_ happen, unless there is a
|
||||
* bug in the server, but we're adding this check just to double-check that the
|
||||
* client app is resilient to a potential issue with the update check.
|
||||
* 4) On Android: the server said there is an update, but the update's hash is the
|
||||
* same as that of the binary's currently running version. We did not attach the
|
||||
* binary's hash to the updateCheck request because we want to avoid having to
|
||||
* install diff updates against the binary's version, which we can't do yet on
|
||||
* Android.
|
||||
* 4) The server said there is an update, but the update's hash is the same as that
|
||||
* of the binary's currently running version. This should only happen in Android -
|
||||
* unlike iOS, we don't attach the binary's hash to the updateCheck request
|
||||
* because we want to avoid having to install diff updates against the binary's
|
||||
* version, which we can't do yet on Android.
|
||||
*/
|
||||
if (!update || update.updateAppVersion || localPackage && (update.packageHash === localPackage.packageHash)) {
|
||||
if (!update || update.updateAppVersion || localPackage && (update.packageHash === localPackage.packageHash) || config.packageHash === localPackage.packageHash) {
|
||||
if (update && update.updateAppVersion) {
|
||||
log("An update is available but it is targeting a newer binary version than you are currently running.");
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
if (Platform.OS === "android" && !localPackage) {
|
||||
const binaryHash = await NativeCodePush.getBinaryHash();
|
||||
if (update.packageHash === binaryHash) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
const remotePackage = { ...update, ...PackageMixins.remote(sdk.reportStatusDownload) };
|
||||
remotePackage.failedInstall = await NativeCodePush.isFailedUpdate(remotePackage.packageHash);
|
||||
remotePackage.deploymentKey = deploymentKey || nativeConfig.deploymentKey;
|
||||
|
||||
@@ -50,7 +50,6 @@ public class CodePush {
|
||||
|
||||
private final String ASSETS_BUNDLE_PREFIX = "assets://";
|
||||
private final String BINARY_MODIFIED_TIME_KEY = "binaryModifiedTime";
|
||||
private final String CODE_PUSH_HASH_FILE_NAME = "CodePushHash.json";
|
||||
private final String CODE_PUSH_PREFERENCES = "CodePush";
|
||||
private final String DOWNLOAD_PROGRESS_EVENT_NAME = "CodePushDownloadProgress";
|
||||
private final String FAILED_UPDATES_KEY = "CODE_PUSH_FAILED_UPDATES";
|
||||
@@ -70,9 +69,9 @@ public class CodePush {
|
||||
private CodePushTelemetryManager codePushTelemetryManager;
|
||||
|
||||
// Config properties.
|
||||
private String deploymentKey;
|
||||
private String appVersion;
|
||||
private int buildVersion;
|
||||
private String deploymentKey;
|
||||
private final String serverUrl = "https://codepush.azurewebsites.net/";
|
||||
|
||||
private Activity mainActivity;
|
||||
@@ -393,20 +392,6 @@ public class CodePush {
|
||||
asyncTask.execute();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getBinaryHash(Promise promise) {
|
||||
try {
|
||||
promise.resolve(CodePushUtils.getStringFromInputStream(mainActivity.getAssets().open(CODE_PUSH_HASH_FILE_NAME)));
|
||||
} catch (IOException e) {
|
||||
if (!isDebugMode) {
|
||||
// Only print this message in "Release" mode. In "Debug", we may not have the
|
||||
// hash if the build skips bundling the files.
|
||||
CodePushUtils.log("Unable to get the hash of the binary's bundled resources - \"codepush.gradle\" may have not been added to the build definition.");
|
||||
}
|
||||
promise.resolve("");
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getConfiguration(Promise promise) {
|
||||
WritableNativeMap configMap = new WritableNativeMap();
|
||||
@@ -417,6 +402,11 @@ public class CodePush {
|
||||
configMap.putString("clientUniqueId",
|
||||
Settings.Secure.getString(mainActivity.getContentResolver(),
|
||||
android.provider.Settings.Secure.ANDROID_ID));
|
||||
String binaryHash = CodePushUpdateUtils.getHashForBinaryContents(mainActivity, isDebugMode);
|
||||
if (binaryHash != null) {
|
||||
configMap.putString(PACKAGE_HASH_KEY, binaryHash);
|
||||
}
|
||||
|
||||
promise.resolve(configMap);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.microsoft.codepush.react;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
@@ -21,6 +22,12 @@ import java.util.Collections;
|
||||
|
||||
public class CodePushUpdateUtils {
|
||||
|
||||
private static final String CODE_PUSH_HASH_FILE_NAME = "CodePushHash.json";
|
||||
|
||||
// These variables are used to cache the hash of the binary contents in memory.
|
||||
private static String binaryHash = null;
|
||||
private static boolean didLoadBinaryHash = false;
|
||||
|
||||
private static void addContentsOfFolderToManifest(String folderPath, String pathPrefix, ArrayList<String> manifest) {
|
||||
File folder = new File(folderPath);
|
||||
File[] folderFiles = folder.listFiles();
|
||||
@@ -102,6 +109,25 @@ public class CodePushUpdateUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getHashForBinaryContents(Activity mainActivity, boolean isDebugMode) {
|
||||
if (!didLoadBinaryHash) {
|
||||
didLoadBinaryHash = true;
|
||||
try {
|
||||
binaryHash = CodePushUtils.getStringFromInputStream(mainActivity.getAssets().open(CODE_PUSH_HASH_FILE_NAME));
|
||||
} catch (IOException e) {
|
||||
if (!isDebugMode) {
|
||||
// Only print this message in "Release" mode. In "Debug", we may not have the
|
||||
// hash if the build skips bundling the files.
|
||||
CodePushUtils.log("Unable to get the hash of the binary's bundled resources - \"codepush.gradle\" may have not been added to the build definition.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return binaryHash;
|
||||
}
|
||||
|
||||
public static void verifyHashForDiffUpdate(String folderPath, String expectedHash) {
|
||||
ArrayList<String> updateContentsManifest = new ArrayList<String>();
|
||||
addContentsOfFolderToManifest(folderPath, "", updateContentsManifest);
|
||||
|
||||
@@ -115,13 +115,14 @@ failCallback:(void (^)(NSError *err))failCallback;
|
||||
+ (NSString *)findMainBundleInFolder:(NSString *)folderPath
|
||||
error:(NSError **)error;
|
||||
|
||||
+ (NSString *)getDefaultAssetsFolderName;
|
||||
+ (NSString *)getAssetsFolderName;
|
||||
+ (NSString *)getDefaultJsBundleName;
|
||||
|
||||
+ (NSString *)getHashForBinaryContents:(NSURL *)binaryBundleUrl
|
||||
error:(NSError **)error;
|
||||
|
||||
+ (NSString *)getManifestFolderPrefix;
|
||||
+ (NSString *)modifiedDateStringOfFileAtURL:(NSURL *)fileURL;
|
||||
|
||||
+ (BOOL)verifyHashForDiffUpdate:(NSString *)finalUpdateFolder
|
||||
expectedHash:(NSString *)expectedHash
|
||||
|
||||
@@ -93,7 +93,7 @@ static NSString *bundleResourceName = @"main";
|
||||
NSString *packageDate = [currentPackageMetadata objectForKey:BinaryBundleDateKey];
|
||||
NSString *packageAppVersion = [currentPackageMetadata objectForKey:AppVersionKey];
|
||||
|
||||
if ([[self modifiedDateStringOfFileAtURL:binaryBundleURL] isEqualToString:packageDate] && ([CodePush isUsingTestConfiguration] ||[binaryAppVersion isEqualToString:packageAppVersion])) {
|
||||
if ([[CodePushUpdateUtils modifiedDateStringOfFileAtURL:binaryBundleURL] isEqualToString:packageDate] && ([CodePush isUsingTestConfiguration] ||[binaryAppVersion isEqualToString:packageAppVersion])) {
|
||||
// Return package file because it is newer than the app store binary's JS bundle
|
||||
NSURL *packageUrl = [[NSURL alloc] initFileURLWithPath:packageFile];
|
||||
NSLog(logMessageFormat, packageUrl);
|
||||
@@ -288,20 +288,6 @@ static NSString *bundleResourceName = @"main";
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the modified date as a string for a given file URL.
|
||||
*/
|
||||
+ (NSString *)modifiedDateStringOfFileAtURL:(NSURL *)fileURL
|
||||
{
|
||||
if (fileURL != nil) {
|
||||
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:nil];
|
||||
NSDate *modifiedDate = [fileAttributes objectForKey:NSFileModificationDate];
|
||||
return [NSString stringWithFormat:@"%f", [modifiedDate timeIntervalSince1970]];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is used when an update has failed installation
|
||||
* and the app needs to be rolled back to the previous bundle.
|
||||
@@ -398,7 +384,7 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
|
||||
NSDictionary *mutableUpdatePackage = [updatePackage mutableCopy];
|
||||
NSURL *binaryBundleURL = [CodePush binaryBundleURL];
|
||||
if (binaryBundleURL != nil) {
|
||||
[mutableUpdatePackage setValue:[CodePush modifiedDateStringOfFileAtURL:binaryBundleURL]
|
||||
[mutableUpdatePackage setValue:[CodePushUpdateUtils modifiedDateStringOfFileAtURL:binaryBundleURL]
|
||||
forKey:BinaryBundleDateKey];
|
||||
}
|
||||
|
||||
@@ -449,7 +435,29 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
|
||||
RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
resolve([[CodePushConfig current] configuration]);
|
||||
NSDictionary *configuration = [[CodePushConfig current] configuration];
|
||||
NSError *error;
|
||||
if (isRunningBinaryVersion) {
|
||||
// isRunningBinaryVersion will not get set to "YES" if running against the packager.
|
||||
NSString *binaryHash = [CodePushUpdateUtils getHashForBinaryContents:[CodePush binaryBundleURL] error:&error];
|
||||
if (error) {
|
||||
NSLog(@"Error obtaining hash for binary contents: %@", error);
|
||||
resolve(configuration);
|
||||
return;
|
||||
}
|
||||
|
||||
if (binaryHash == nil) {
|
||||
resolve(configuration);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *mutableConfiguration = [configuration mutableCopy];
|
||||
[mutableConfiguration setObject:binaryHash forKey:PackageHashKey];
|
||||
resolve(mutableConfiguration);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(configuration);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,25 +467,6 @@ RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSError *error;
|
||||
if (isRunningBinaryVersion) {
|
||||
// isRunningBinaryVersion will not get set to "YES" if running against the packager.
|
||||
NSString *binaryHash = [CodePushUpdateUtils getHashForBinaryContents:[CodePush binaryBundleURL] error:&error];
|
||||
if (error) {
|
||||
NSLog(@"Error obtaining hash for binary contents: %@", error);
|
||||
resolve(nil);
|
||||
return;
|
||||
} else if (binaryHash == nil) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(@{
|
||||
PackageHashKey:binaryHash,
|
||||
AppVersionKey:[[CodePushConfig current] appVersion]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *package = [[CodePushPackage getCurrentPackage:&error] mutableCopy];
|
||||
|
||||
if (error) {
|
||||
|
||||
@@ -15,7 +15,7 @@ NSString * const UnzippedFolderName = @"unzipped";
|
||||
|
||||
+ (NSString *)getBinaryAssetsPath
|
||||
{
|
||||
return [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[CodePushUpdateUtils getDefaultAssetsFolderName]];
|
||||
return [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[CodePushUpdateUtils getAssetsFolderName]];
|
||||
}
|
||||
|
||||
+ (NSString *)getCodePushPath
|
||||
@@ -286,7 +286,7 @@ NSString * const UnzippedFolderName = @"unzipped";
|
||||
}
|
||||
|
||||
[[NSFileManager defaultManager] copyItemAtPath:[self getBinaryAssetsPath]
|
||||
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[CodePushUpdateUtils getDefaultAssetsFolderName]]
|
||||
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[CodePushUpdateUtils getAssetsFolderName]]
|
||||
error:&error];
|
||||
if (error) {
|
||||
failCallback(error);
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
|
||||
@implementation CodePushUpdateUtils
|
||||
|
||||
NSString * const ManifestFolderPrefix = @"CodePush";
|
||||
NSString * const AssetsFolderName = @"assets";
|
||||
NSString * const BinaryHashKey = @"CodePushBinaryHash";
|
||||
NSString * const DefaultJsBundleName = @"main.jsbundle";
|
||||
NSString * const DefaultAssetsFolderName = @"assets";
|
||||
NSString * const ManifestFolderPrefix = @"CodePush";
|
||||
|
||||
// These variables are used to cache the hash of the binary contents in memory.
|
||||
static NSString *binaryHash = nil;
|
||||
static BOOL didLoadBinaryHash = false;
|
||||
|
||||
+ (void)addContentsOfFolderToManifest:(NSString *)folderPath
|
||||
pathPrefix:(NSString *)pathPrefix
|
||||
@@ -34,13 +39,32 @@ NSString * const DefaultAssetsFolderName = @"assets";
|
||||
}
|
||||
} else {
|
||||
NSData *fileContents = [NSData dataWithContentsOfFile:fullFilePath];
|
||||
NSString *fileContentsHash = [self computeHash:fileContents];
|
||||
NSString *fileContentsHash = [self computeHashForData:fileContents];
|
||||
[manifest addObject:[[relativePath stringByAppendingString:@":"] stringByAppendingString:fileContentsHash]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)computeHash:(NSData *)inputData
|
||||
+ (NSString *)computeFinalHashFromManifest:(NSMutableArray *)manifest
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSArray *sortedManifest = [manifest sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSData *manifestData = [NSJSONSerialization dataWithJSONObject:sortedManifest
|
||||
options:kNilOptions
|
||||
error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *manifestString = [[NSString alloc] initWithData:manifestData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
// The JSON serialization turns path separators into "\/", e.g. "CodePush\/assets\/image.png"
|
||||
manifestString = [manifestString stringByReplacingOccurrencesOfString:@"\\/"
|
||||
withString:@"/"];
|
||||
return [self computeHashForData:[NSData dataWithBytes:manifestString.UTF8String length:manifestString.length]];
|
||||
}
|
||||
|
||||
+ (NSString *)computeHashForData:(NSData *)inputData
|
||||
{
|
||||
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256(inputData.bytes, inputData.length, digest);
|
||||
@@ -131,9 +155,9 @@ NSString * const DefaultAssetsFolderName = @"assets";
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSString *)getDefaultAssetsFolderName
|
||||
+ (NSString *)getAssetsFolderName
|
||||
{
|
||||
return DefaultAssetsFolderName;
|
||||
return AssetsFolderName;
|
||||
}
|
||||
|
||||
+ (NSString *)getDefaultJsBundleName
|
||||
@@ -144,35 +168,50 @@ NSString * const DefaultAssetsFolderName = @"assets";
|
||||
+ (NSString *)getHashForBinaryContents:(NSURL *)binaryBundleUrl
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSString *assetsPath = [CodePushPackage getBinaryAssetsPath];
|
||||
NSMutableArray *manifest = [NSMutableArray array];
|
||||
[self addContentsOfFolderToManifest:assetsPath
|
||||
pathPrefix:[NSString stringWithFormat:@"%@/%@", [self getManifestFolderPrefix], @"assets"]
|
||||
manifest:manifest
|
||||
error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
if (!didLoadBinaryHash) {
|
||||
didLoadBinaryHash = true;
|
||||
|
||||
// Get the cached hash from user preferences if it exists.
|
||||
NSString *binaryModifiedDate = [self modifiedDateStringOfFileAtURL:binaryBundleUrl];
|
||||
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableDictionary *binaryHashDictionary = [preferences objectForKey:BinaryHashKey];
|
||||
if (binaryHashDictionary != nil) {
|
||||
binaryHash = [binaryHashDictionary objectForKey:binaryModifiedDate];
|
||||
if (binaryHash == nil) {
|
||||
[preferences removeObjectForKey:BinaryHashKey];
|
||||
[preferences synchronize];
|
||||
} else {
|
||||
return binaryHash;
|
||||
}
|
||||
}
|
||||
|
||||
binaryHashDictionary = [NSMutableDictionary dictionary];
|
||||
|
||||
NSString *assetsPath = [CodePushPackage getBinaryAssetsPath];
|
||||
NSMutableArray *manifest = [NSMutableArray array];
|
||||
[self addContentsOfFolderToManifest:assetsPath
|
||||
pathPrefix:[NSString stringWithFormat:@"%@/%@", [self getManifestFolderPrefix], @"assets"]
|
||||
manifest:manifest
|
||||
error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSData *jsBundleContents = [NSData dataWithContentsOfURL:binaryBundleUrl];
|
||||
NSString *jsBundleContentsHash = [self computeHashForData:jsBundleContents];
|
||||
[manifest addObject:[[NSString stringWithFormat:@"%@/%@", [self getManifestFolderPrefix], [self getDefaultJsBundleName]] stringByAppendingString:jsBundleContentsHash]];
|
||||
binaryHash = [self computeFinalHashFromManifest:manifest error:error];
|
||||
|
||||
// Cache the hash in user preferences. This assumes that the modified date for the
|
||||
// JS bundle changes every time a new bundle is generated by the packager.
|
||||
[binaryHashDictionary setObject:binaryHash forKey:binaryModifiedDate];
|
||||
[preferences setObject:binaryHashDictionary forKey:BinaryHashKey];
|
||||
[preferences synchronize];
|
||||
return binaryHash;
|
||||
}
|
||||
|
||||
NSData *jsBundleContents = [NSData dataWithContentsOfURL:binaryBundleUrl];
|
||||
NSString *jsBundleContentsHash = [self computeHash:jsBundleContents];
|
||||
[manifest addObject:[[NSString stringWithFormat:@"%@/%@", [self getManifestFolderPrefix], [self getDefaultJsBundleName]] stringByAppendingString:jsBundleContentsHash]];
|
||||
|
||||
NSArray *sortedManifest = [manifest sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSData *manifestData = [NSJSONSerialization dataWithJSONObject:sortedManifest
|
||||
options:kNilOptions
|
||||
error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *manifestString = [[NSString alloc] initWithData:manifestData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
// The JSON serialization turns path separators into "\/", e.g. "CodePush\/assets\/image.png"
|
||||
manifestString = [manifestString stringByReplacingOccurrencesOfString:@"\\/"
|
||||
withString:@"/"];
|
||||
NSString *manifestHash = [self computeHash:[NSData dataWithBytes:manifestString.UTF8String length:manifestString.length]];
|
||||
return manifestHash;
|
||||
// Use the cached hash in memory.
|
||||
return binaryHash;
|
||||
}
|
||||
|
||||
+ (NSString *)getManifestFolderPrefix
|
||||
@@ -180,6 +219,17 @@ NSString * const DefaultAssetsFolderName = @"assets";
|
||||
return ManifestFolderPrefix;
|
||||
}
|
||||
|
||||
+ (NSString *)modifiedDateStringOfFileAtURL:(NSURL *)fileURL
|
||||
{
|
||||
if (fileURL != nil) {
|
||||
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:nil];
|
||||
NSDate *modifiedDate = [fileAttributes objectForKey:NSFileModificationDate];
|
||||
return [NSString stringWithFormat:@"%f", [modifiedDate timeIntervalSince1970]];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)verifyHashForDiffUpdate:(NSString *)finalUpdateFolder
|
||||
expectedHash:(NSString *)expectedHash
|
||||
error:(NSError **)error
|
||||
@@ -193,20 +243,12 @@ NSString * const DefaultAssetsFolderName = @"assets";
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSArray *sortedUpdateContentsManifest = [updateContentsManifest sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSData *updateContentsManifestData = [NSJSONSerialization dataWithJSONObject:sortedUpdateContentsManifest
|
||||
options:kNilOptions
|
||||
error:error];
|
||||
if (*error) {
|
||||
NSString *updateContentsManifestHash = [self computeFinalHashFromManifest:updateContentsManifest
|
||||
error:error];
|
||||
if (*error || updateContentsManifestHash == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *updateContentsManifestString = [[NSString alloc] initWithData:updateContentsManifestData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
// The JSON serialization turns path separators into "\/", e.g. "CodePush\/assets\/image.png"
|
||||
updateContentsManifestString = [updateContentsManifestString stringByReplacingOccurrencesOfString:@"\\/"
|
||||
withString:@"/"];
|
||||
NSString *updateContentsManifestHash = [self computeHash:[NSData dataWithBytes:updateContentsManifestString.UTF8String length:updateContentsManifestString.length]];
|
||||
|
||||
return [updateContentsManifestHash isEqualToString:expectedHash];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user