Defaults.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //
  2. // Defaults.m
  3. // MG
  4. //
  5. // Created by Tim Debo on 6/1/14.
  6. //
  7. //
  8. #import "Defaults.h"
  9. #import "WindowController.h"
  10. #import "Event.h"
  11. #import "JSON.h"
  12. typedef id (^ReturnType)();
  13. typedef void (^SetType)();
  14. @interface Defaults ()
  15. - (NSString*) addPrefix:(NSString*)key;
  16. @end
  17. @implementation Defaults
  18. @synthesize defaults;
  19. - (id) initWithWindowController:(WindowController *)aWindowController
  20. {
  21. self = [super init];
  22. if(self) {
  23. self.windowController = aWindowController;
  24. self.webView = aWindowController.webView;
  25. [[NSNotificationCenter defaultCenter] addObserver:self
  26. selector:@selector(defaultsChanged:)
  27. name:NSUserDefaultsDidChangeNotification
  28. object:nil];
  29. }
  30. return self;
  31. }
  32. - (void)dealloc
  33. {
  34. [[NSNotificationCenter defaultCenter] removeObserver: self];
  35. }
  36. - (JSValue*) defaults
  37. {
  38. return [JSValue valueWithObject: [self defaultsDictionary] inContext: [JSContext currentContext] ];
  39. }
  40. - (JSValue*) get:(NSString *)key ofType:(NSString *)type
  41. {
  42. if(!key || [key isKindOfClass:[NSNull class]])
  43. return nil;
  44. if(!type || [type isKindOfClass:[NSNull class]]) {
  45. type = @"string";
  46. }
  47. NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
  48. NSString* pfxKey = [self addPrefix:key];
  49. NSDictionary *types = @{
  50. @"string" : ^{ return [prefs stringForKey:pfxKey];},
  51. @"int" : ^{ return [NSNumber numberWithInteger:[prefs integerForKey:pfxKey]]; },
  52. @"bool" : ^{ return [NSNumber numberWithBool:[prefs boolForKey:pfxKey]]; },
  53. @"float" : ^{ return [NSNumber numberWithFloat:[prefs floatForKey:pfxKey]]; },
  54. @"url" : ^{ return [[prefs URLForKey:pfxKey] absoluteString]; },
  55. @"object" : ^{ return [prefs dictionaryForKey:pfxKey]; }
  56. };
  57. id returnVal = nil;
  58. ReturnType theType = types[type];
  59. if(theType) {
  60. returnVal = theType();
  61. } else {
  62. //nil for now but we really should raise a JS Exception for this..
  63. return nil;
  64. }
  65. return [JSValue valueWithObject: returnVal inContext:[JSContext currentContext]];
  66. }
  67. - (void) setKey:(NSString*)key withValue: (JSValue*) value ofType: (NSString*) type
  68. {
  69. if(!key || [key isKindOfClass:[NSNull class]])
  70. return;
  71. if(!type || [type isKindOfClass:[NSNull class]]) {
  72. type = @"string";
  73. }
  74. NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
  75. NSString* pfxKey = [self addPrefix:key];
  76. NSDictionary *types = @{
  77. @"string" : ^{ [prefs setObject: [value toString] forKey:pfxKey]; DebugNSLog(@"Set String: %@", value); },
  78. @"int" : ^{ [prefs setInteger: [value toInt32] forKey:pfxKey]; DebugNSLog(@"Set int: %@",value);},
  79. @"bool" : ^{ [prefs setBool: [value toBool] forKey:pfxKey]; DebugNSLog(@"Set bool: %@",value);},
  80. @"float" : ^{ [prefs setFloat: [[value toNumber] floatValue] forKey:pfxKey]; DebugNSLog(@"Set float: %@",value);},
  81. @"url" : ^{ [prefs setURL:[NSURL URLWithString: [value toString]] forKey:pfxKey]; DebugNSLog(@"Set url: %@",value);},
  82. };
  83. ((SetType) types[type])();
  84. }
  85. - (void) remove: (NSString*) key
  86. {
  87. NSString* prefixedKey;
  88. prefixedKey = [self addPrefix:key];
  89. [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey];
  90. [[NSUserDefaults standardUserDefaults] synchronize];
  91. }
  92. // Check we have a standard prefix for JS-modified keys, for security purposes.
  93. // If not, add it. This stops JavaScript from ever being able to modify keys
  94. // it did not create.
  95. - (NSString*) addPrefix:(NSString*)key {
  96. NSString* prefix;
  97. prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
  98. if (![key hasPrefix:prefix]) {
  99. key = [prefix stringByAppendingString:key];
  100. }
  101. return key;
  102. }
  103. - (void)defaultsChanged:(NSNotification *)notification {
  104. NSDictionary* returnDict = [self defaultsDictionary];
  105. [Event triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView];
  106. }
  107. - (NSDictionary*) defaultsDictionary {
  108. NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
  109. NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init];
  110. // Get the user defaults.
  111. NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
  112. [[defs dictionaryRepresentation] enumerateKeysAndObjectsUsingBlock:^( id key, id val, BOOL *stop) {
  113. if([key hasPrefix: prefix]) {
  114. [returnDict setObject: val forKey: key];
  115. }
  116. }];
  117. return returnDict;
  118. }
  119. @end