[RN Events] clear disk cache on logout

This commit is contained in:
Spencer Ahrens 2015-06-18 09:29:31 -07:00
parent 58d01c7981
commit dc393162c3
2 changed files with 53 additions and 19 deletions

View File

@ -8,6 +8,7 @@
*/ */
#import "RCTBridgeModule.h" #import "RCTBridgeModule.h"
#import "RCTInvalidating.h"
/** /**
* A simple, asynchronous, persistent, key-value storage system designed as a * A simple, asynchronous, persistent, key-value storage system designed as a
@ -20,7 +21,9 @@
* *
* Keys and values must always be strings or an error is returned. * Keys and values must always be strings or an error is returned.
*/ */
@interface RCTAsyncLocalStorage : NSObject <RCTBridgeModule> @interface RCTAsyncLocalStorage : NSObject <RCTBridgeModule,RCTInvalidating>
@property (nonatomic, assign) BOOL clearOnInvalidate;
- (void)multiGet:(NSArray *)keys callback:(RCTResponseSenderBlock)callback; - (void)multiGet:(NSArray *)keys callback:(RCTResponseSenderBlock)callback;
- (void)multiSet:(NSArray *)kvPairs callback:(RCTResponseSenderBlock)callback; - (void)multiSet:(NSArray *)kvPairs callback:(RCTResponseSenderBlock)callback;
@ -28,4 +31,7 @@
- (void)clear:(RCTResponseSenderBlock)callback; - (void)clear:(RCTResponseSenderBlock)callback;
- (void)getAllKeys:(RCTResponseSenderBlock)callback; - (void)getAllKeys:(RCTResponseSenderBlock)callback;
// For clearing data when the bridge may not exist, e.g. when logging out.
+ (NSError *)clearAllData;
@end @end

View File

@ -61,6 +61,13 @@ static id RCTReadFile(NSString *filePath, NSString *key, NSDictionary **errorOut
return nil; return nil;
} }
static NSString *RCTGetStorageDir()
{
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSURL *homeURL = [NSURL fileURLWithPath:documentDirectory isDirectory:YES];
return [[homeURL URLByAppendingPathComponent:kStorageDir isDirectory:YES] path];
}
// Only merges objects - all other types are just clobbered (including arrays) // Only merges objects - all other types are just clobbered (including arrays)
static void RCTMergeRecursive(NSMutableDictionary *destination, NSDictionary *source) static void RCTMergeRecursive(NSMutableDictionary *destination, NSDictionary *source)
{ {
@ -106,7 +113,39 @@ RCT_EXPORT_MODULE()
- (dispatch_queue_t)methodQueue - (dispatch_queue_t)methodQueue
{ {
return dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL); // We want all instances to share the same queue since they will be reading/writing the same files.
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
});
return queue;
}
+ (NSError *)clearAllData
{
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath:RCTGetStorageDir() error:&error];
return error;
}
- (void)invalidate
{
if (_clearOnInvalidate) {
[RCTAsyncLocalStorage clearAllData];
}
_clearOnInvalidate = NO;
_manifest = [[NSMutableDictionary alloc] init];
_haveSetup = NO;
}
- (BOOL)isValid
{
return _haveSetup;
}
- (void)dealloc
{
[self invalidate];
} }
- (NSString *)_filePathForKey:(NSString *)key - (NSString *)_filePathForKey:(NSString *)key
@ -120,10 +159,7 @@ RCT_EXPORT_MODULE()
if (_haveSetup) { if (_haveSetup) {
return nil; return nil;
} }
NSString *documentDirectory = _storageDirectory = RCTGetStorageDir();
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSURL *homeURL = [NSURL fileURLWithPath:documentDirectory isDirectory:YES];
_storageDirectory = [[homeURL URLByAppendingPathComponent:kStorageDir isDirectory:YES] path];
NSError *error; NSError *error;
[[NSFileManager defaultManager] createDirectoryAtPath:_storageDirectory [[NSFileManager defaultManager] createDirectoryAtPath:_storageDirectory
withIntermediateDirectories:YES withIntermediateDirectories:YES
@ -135,10 +171,10 @@ RCT_EXPORT_MODULE()
_manifestPath = [_storageDirectory stringByAppendingPathComponent:kManifestFilename]; _manifestPath = [_storageDirectory stringByAppendingPathComponent:kManifestFilename];
NSDictionary *errorOut; NSDictionary *errorOut;
NSString *serialized = RCTReadFile(_manifestPath, nil, &errorOut); NSString *serialized = RCTReadFile(_manifestPath, nil, &errorOut);
_manifest = serialized ? [RCTJSONParse(serialized, &error) mutableCopy] : [NSMutableDictionary new]; _manifest = serialized ? [RCTJSONParse(serialized, &error) mutableCopy] : [[NSMutableDictionary alloc] init];
if (error) { if (error) {
RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error); RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error);
_manifest = [NSMutableDictionary new]; _manifest = [[NSMutableDictionary alloc] init];
} }
_haveSetup = YES; _haveSetup = YES;
return nil; return nil;
@ -312,18 +348,10 @@ RCT_EXPORT_METHOD(multiRemove:(NSArray *)keys
RCT_EXPORT_METHOD(clear:(RCTResponseSenderBlock)callback) RCT_EXPORT_METHOD(clear:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; _manifest = [[NSMutableDictionary alloc] init];
if (!errorOut) { NSError *error = [RCTAsyncLocalStorage clearAllData];
NSError *error;
for (NSString *key in _manifest) {
NSString *filePath = [self _filePathForKey:key];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
}
[_manifest removeAllObjects];
errorOut = [self _writeManifest:nil];
}
if (callback) { if (callback) {
callback(@[RCTNullIfNil(errorOut)]); callback(@[RCTNullIfNil(error)]);
} }
} }