incubator-callback-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shaz...@apache.org
Subject [2/2] ios commit: Fixed CB-330 - localStorage / SQLDatabase no longer persistent after iOS 5.01 update Fixed CB-347 - iOS 5.1 localStorage / SQLDatabase error after upgrading an app
Date Tue, 20 Mar 2012 22:53:44 GMT
Fixed CB-330 - localStorage / SQLDatabase no longer persistent after iOS 5.01 update
Fixed CB-347 - iOS 5.1 localStorage / SQLDatabase error after upgrading an app


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/20527867
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/20527867
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/20527867

Branch: refs/heads/master
Commit: 20527867f4958c331e34aeb4dd83695756e13585
Parents: 1a9027e
Author: Shazron Abdullah <shazron@apache.org>
Authored: Tue Mar 20 15:20:01 2012 -0700
Committer: Shazron Abdullah <shazron@apache.org>
Committed: Tue Mar 20 15:20:01 2012 -0700

----------------------------------------------------------------------
 CordovaLib/Classes/CDV.h                        |    1 +
 CordovaLib/Classes/CDVAvailability.h            |   10 +
 CordovaLib/Classes/CDVCommandDelegate.h         |    3 +
 CordovaLib/Classes/CDVLocalStorage.h            |   41 +++
 CordovaLib/Classes/CDVLocalStorage.m            |  299 ++++++++++++++++++
 CordovaLib/Classes/CDVViewController.m          |   43 ++--
 CordovaLib/CordovaLib.xcodeproj/project.pbxproj |   12 +
 7 files changed, 389 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDV.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDV.h b/CordovaLib/Classes/CDV.h
index 414ac59..b4e4ecd 100644
--- a/CordovaLib/Classes/CDV.h
+++ b/CordovaLib/Classes/CDV.h
@@ -45,6 +45,7 @@
 #import "CDVSound.h"
 #import "CDVSplashScreen.h"
 #import "CDVWhitelist.h"
+#import "CDVLocalStorage.h"
 
 #import "NSData+Base64.h"
 #import "NSDictionary+Extensions.h"

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDVAvailability.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVAvailability.h b/CordovaLib/Classes/CDVAvailability.h
index 363d175..ea643ff 100644
--- a/CordovaLib/Classes/CDVAvailability.h
+++ b/CordovaLib/Classes/CDVAvailability.h
@@ -38,3 +38,13 @@
 #ifndef CORDOVA_VERSION_MIN_REQUIRED
     #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_1_5_0
 #endif
+
+/* 
+ Returns YES if it is at least version specified as NSString(X)
+ Usage: 
+     if (IsiOSVersion(@"5.1")) {
+         // do something for iOS 5.1 or greater
+     }
+ */
+#define IsiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch]
!= NSOrderedAscending)
+

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDVCommandDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVCommandDelegate.h b/CordovaLib/Classes/CDVCommandDelegate.h
index 7b379b5..74aef38 100644
--- a/CordovaLib/Classes/CDVCommandDelegate.h
+++ b/CordovaLib/Classes/CDVCommandDelegate.h
@@ -19,10 +19,13 @@
 
 #import "CDVInvokedUrlCommand.h"
 
+@class CDVPlugin;
+
 @protocol CDVCommandDelegate <NSObject>
 
 - (NSString*) pathForResource:(NSString*)resourcepath;
 - (id) getCommandInstance:(NSString*)pluginName;
+- (void) registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className;
 - (BOOL) execute:(CDVInvokedUrlCommand*)command;
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDVLocalStorage.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocalStorage.h b/CordovaLib/Classes/CDVLocalStorage.h
new file mode 100644
index 0000000..0abd43d
--- /dev/null
+++ b/CordovaLib/Classes/CDVLocalStorage.h
@@ -0,0 +1,41 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPlugin.h"
+
+#define kCDVLocalStorageErrorDomain @"kCDVLocalStorageErrorDomain" 
+#define kCDVLocalStorageFileOperationError  1
+
+@interface CDVLocalStorage : CDVPlugin < UIWebViewDelegate >
+
+@property (nonatomic, readonly, retain) NSMutableArray* backupInfo;
+
+- (void)  backup:(NSArray*)arguments withDict:(NSMutableDictionary*)options;
+- (void) restore:(NSArray*)arguments withDict:(NSMutableDictionary*)options;
+- (void) verifyAndFixDatabaseLocations:(NSArray*)arguments withDict:(NSMutableDictionary*)options;
+
+@end
+
+@interface CDVBackupInfo : NSObject
+
+@property (nonatomic, copy) NSString* original;
+@property (nonatomic, copy) NSString* backup;
+@property (nonatomic, copy) NSString* label;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDVLocalStorage.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocalStorage.m b/CordovaLib/Classes/CDVLocalStorage.m
new file mode 100644
index 0000000..fbd5d1c
--- /dev/null
+++ b/CordovaLib/Classes/CDVLocalStorage.m
@@ -0,0 +1,299 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVLocalStorage.h"
+#import "CDV.h"
+
+@interface CDVLocalStorage ()
+
+@property (nonatomic, readwrite, retain) NSMutableArray* backupInfo;  // array of CDVBackupInfo
objects
+@property (nonatomic, readwrite, assign) id<UIWebViewDelegate> webviewDelegate;
+
+@end
+
+
+@implementation CDVLocalStorage
+
+@synthesize backupInfo, webviewDelegate;
+
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView
+{
+    self = (CDVLocalStorage*)[super initWithWebView:theWebView];
+    if (self) 
+    {
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResignActive)

+                                                     name:UIApplicationWillResignActiveNotification
object:nil];
+        
+        NSString *original, *backup;
+        self.backupInfo = [NSMutableArray arrayWithCapacity:3];
+        
+        // set up common folders
+        NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask, YES)objectAtIndex:0];
+        NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
+        NSString* backupsFolder = [appDocumentsFolder stringByAppendingPathComponent:@"Backups"];
+        
+        // create the backups folder
+        [[NSFileManager defaultManager] createDirectoryAtPath:backupsFolder withIntermediateDirectories:YES
attributes:nil error:nil];
+
+        //////////// LOCALSTORAGE
+        
+        original = [[appLibraryFolder stringByAppendingPathComponent:
+                                 (IsiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/LocalStorage"]
+                                 stringByAppendingPathComponent:@"file__0.localstorage"];

+                                   
+        backup = [backupsFolder stringByAppendingPathComponent:@"localstorage.appdata.db"];
+        
+        CDVBackupInfo* backupItem = [[[CDVBackupInfo alloc] init] autorelease];
+        backupItem.backup = backup;
+        backupItem.original = original;
+        backupItem.label = @"localStorage database";
+        
+        [self.backupInfo addObject:backupItem];
+        
+        //////////// WEBSQL MAIN DB
+
+        original = [[appLibraryFolder stringByAppendingPathComponent:
+                     (IsiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/Databases"]
+                    stringByAppendingPathComponent:@"Databases.db"]; 
+        
+        backup = [backupsFolder stringByAppendingPathComponent:@"websqlmain.appdata.db"];
+        
+        backupItem = [[[CDVBackupInfo alloc] init] autorelease];
+        backupItem.backup = backup;
+        backupItem.original = original;
+        backupItem.label = @"websql main database";
+        
+        [self.backupInfo addObject:backupItem];
+        
+        //////////// WEBSQL DATABASES
+        
+        original = [[appLibraryFolder stringByAppendingPathComponent:
+                     (IsiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/Databases"]
+                    stringByAppendingPathComponent:@"file__0"]; 
+        
+        backup = [backupsFolder stringByAppendingPathComponent:@"websqldbs.appdata.db"];
+        
+        backupItem = [[[CDVBackupInfo alloc] init] autorelease];
+        backupItem.backup = backup;
+        backupItem.original = original;
+        backupItem.label = @"websql databases";
+        
+        [self.backupInfo addObject:backupItem];
+
+        ////////////
+        
+        // over-ride current webview delegate (for restore reasons)
+        self.webviewDelegate = theWebView.delegate;
+        theWebView.delegate = self;
+        
+        // verify the and fix the iOS 5.1 database locations once
+        [self verifyAndFixDatabaseLocations:nil withDict:nil];
+    }
+    
+    return self;
+}
+
+#pragma mark -
+#pragma mark Plugin interface methods
+
+- (BOOL) copyFrom:(NSString*)src to:(NSString*)dest error:(NSError**)error
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+    
+    if (![fileManager fileExistsAtPath:src]) {
+
+        NSString* errorString = [NSString stringWithFormat:@"%@ file does not exist.", src];
+        if (error != NULL) {
+            (*error) = [NSError errorWithDomain:kCDVLocalStorageErrorDomain 
+                                           code:kCDVLocalStorageFileOperationError 
+                                       userInfo:[NSDictionary dictionaryWithObject:errorString

+                                                 forKey:NSLocalizedDescriptionKey]];
+        }
+        return NO;
+    }
+    
+    // generate unique filepath in temp directory
+    CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
+    CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
+    NSString* tempBackup = [[NSTemporaryDirectory() stringByAppendingPathComponent:(NSString*)uuidString]
stringByAppendingPathExtension:@"bak"];
+    CFRelease(uuidString);
+    CFRelease(uuidRef);
+    
+    BOOL destExists = [fileManager fileExistsAtPath:dest];
+    
+    // backup the dest
+    if (destExists && ![fileManager copyItemAtPath:dest toPath:tempBackup error:error])
{
+        return NO;
+    } 
+    
+    // remove the dest
+    if (destExists && ![fileManager removeItemAtPath:dest error:error]) { 
+        return NO;
+    } 
+    
+    // copy src to dest
+    if ([fileManager copyItemAtPath:src toPath:dest error:error]) {
+        // success - cleanup - delete the backup to the dest
+        if ([fileManager fileExistsAtPath:tempBackup]) {
+            [fileManager removeItemAtPath:tempBackup error:error]; 
+        }
+        return YES;
+
+    } else {
+        // failure - we restore the temp backup file to dest
+        [fileManager copyItemAtPath:tempBackup toPath:dest error:error];
+        // cleanup - delete the backup to the dest
+        if ([fileManager fileExistsAtPath:tempBackup]) {
+            [fileManager removeItemAtPath:tempBackup error:error]; 
+        }
+        return NO;
+    }
+}
+
+/* copy from webkitDbLocation to persistentDbLocation */
+- (void) backup:(NSArray*)arguments withDict:(NSMutableDictionary*)options;
+{
+    NSError* error = nil;
+    
+    for (CDVBackupInfo* info in self.backupInfo)
+    {
+        [self copyFrom:info.original to:info.backup error:&error];
+        
+        if (error == nil) {
+            NSLog(@"Backed up: %@", info.label);
+        } else {
+            NSLog(@"Error in CDVLocalStorage (%@) backup: %@", info.label, [error localizedDescription]);
+        }
+    }
+}
+
+/* copy from persistentDbLocation to webkitDbLocation */
+- (void) restore:(NSArray*)arguments withDict:(NSMutableDictionary*)options;
+{
+    NSError* error = nil;
+    
+    for (CDVBackupInfo* info in self.backupInfo)
+    {
+        [self copyFrom:info.backup to:info.original error:&error];
+        
+        if (error == nil) {
+            NSLog(@"CDVLocalStorage restored: %@", info.label);
+        } else {
+            NSLog(@"Error in CDVLocalStorage (%@) restore: %@", info.label, [error localizedDescription]);
+        }
+    }
+}
+
+- (void) verifyAndFixDatabaseLocations:(NSArray*)arguments withDict:(NSMutableDictionary*)options
+{
+    NSUserDefaults* appPreferences = [NSUserDefaults standardUserDefaults];
+    NSBundle* mainBundle = [NSBundle mainBundle];
+
+    NSString* bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent];
+    NSString* bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@"CFBundleIdentifier"];
+
+    NSString* appPlistPath = [[bundlePath stringByAppendingPathComponent:@"Library/Preferences"]
stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", bundleIdentifier]];
+    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath];
+    
+    NSArray* keysToCheck = [NSArray arrayWithObjects:
+                            @"WebKitLocalStorageDatabasePathPreferenceKey", @"WebDatabaseDirectory",
nil];
+    
+    
+    BOOL dirty = NO;
+    NSString* pathSuffix =  (IsiOSVersion(@"5.1")) ? @"Library/Caches" : @"Library/WebKit";
+
+    for (NSString* key in keysToCheck) 
+    {
+        NSString* value = [appPlistDict objectForKey:key];
+        // verify path is in app bundle, if not - fix
+        if (![value hasPrefix:bundlePath]) {
+            [appPlistDict setValue:[bundlePath stringByAppendingPathComponent:pathSuffix]
forKey:key];
+            dirty = YES;
+        }
+    }
+    
+    if (dirty) 
+    {
+        BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES];
+        NSLog(@"Fix applied for database locations?: %@", ok? @"YES":@"NO");
+    
+        [appPreferences synchronize];
+    }
+}
+
+#pragma mark -
+#pragma mark Notification handlers
+
+- (void) onResignActive
+{
+    [self backup:nil withDict:nil];    
+}
+
+- (void) onAppTerminate
+{
+    [self backup:nil withDict:nil];    
+}
+
+#pragma mark -
+#pragma mark UIWebviewDelegate implementation and forwarding
+
+- (void) webViewDidStartLoad:(UIWebView*)theWebView
+{
+    [self restore:nil withDict:nil];
+    
+    return [self.webviewDelegate webViewDidStartLoad:theWebView];
+}
+
+- (void) webViewDidFinishLoad:(UIWebView*)theWebView 
+{
+    return [self.webviewDelegate webViewDidFinishLoad:theWebView];
+}
+
+- (void) webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error 
+{
+    return [self.webviewDelegate webView:theWebView didFailLoadWithError:error];
+}
+
+- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
+{
+    return [self.webviewDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
+}
+
+#pragma mark -
+#pragma mark Over-rides
+
+- (void) dealloc
+{
+    self.backupInfo = nil;
+    
+    [super dealloc];
+}
+
+@end
+
+
+#pragma mark -
+#pragma mark CDVBackupInfo implementation
+
+@implementation CDVBackupInfo
+
+@synthesize original, backup, label;
+
+@end
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index 6058e5b..f94814b 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -17,11 +17,7 @@
  under the License.
  */
 
-#import "CDVViewController.h"
-#import "CDVPlugin.h"
-#import "CDVLocation.h"
-#import "CDVConnection.h"
-#import "NSDictionary+Extensions.h"
+#import "CDV.h"
 
 #define SYMBOL_TO_NSSTRING_HELPER(x) @#x
 #define SYMBOL_TO_NSSTRING(x) SYMBOL_TO_NSSTRING_HELPER(x)
@@ -70,6 +66,7 @@
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground:)

                                                      name:UIApplicationDidEnterBackgroundNotification
object:nil];
 
+        self.commandDelegate = self;
         self.wwwFolderName = @"www";
         self.startPage = @"index.html";
         [self setWantsFullScreenLayout:YES];
@@ -170,6 +167,11 @@
     }
     
     /*
+     * Fire up CDVLocalStorage to work-around iOS 5.1 WebKit storage bug limitations
+     */
+    [self.commandDelegate registerPlugin:[[[CDVLocalStorage alloc] initWithWebView:self.webView]
autorelease] withClassName:NSStringFromClass([CDVLocalStorage class])];
+    
+    /*
      * This is for iOS 4.x, where you can allow inline <video> and <audio>, and
also autoplay them
      */
     if ([allowInlineMediaPlayback boolValue] && [self.webView respondsToSelector:@selector(allowsInlineMediaPlayback)])
{
@@ -204,9 +206,6 @@
         NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>",
loadErr];
         [self.webView loadHTMLString:html baseURL:nil];
     }
-    
-	self.commandDelegate = self;
-
 }
 
 - (NSArray*) parseInterfaceOrientations:(NSArray*)orientations
@@ -487,7 +486,7 @@
      */
     else
     {
-        NSLog(@"PGAppDelegate::shouldStartLoadWithRequest: Received Unhandled URL %@", url);
+        NSLog(@"AppDelegate::shouldStartLoadWithRequest: Received Unhandled URL %@", url);
 		
         if ([[UIApplication sharedApplication] canOpenURL:url]) {
             [[UIApplication sharedApplication] openURL:url];
@@ -693,7 +692,6 @@ BOOL gSplashScreenShown = NO;
 	
 	
     // Parse the returned JSON array.
-    //PG_SBJsonParser* jsonParser = [[[PG_SBJsonParser alloc] init] autorelease];
     NSArray* queuedCommands =
 	[queuedCommandsJSON objectFromJSONString];
 	
@@ -769,6 +767,19 @@ BOOL gSplashScreenShown = NO;
     return retVal;
 }
 
+- (void) registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className
+{
+    if ([plugin respondsToSelector:@selector(setViewController:)]) { 
+        [plugin setViewController:self];
+    }
+    
+    if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) { 
+        [plugin setCommandDelegate:self.commandDelegate];
+    }
+    
+    [self.pluginObjects setObject:plugin forKey:className];
+}
+
 /**
  Returns an instance of a CordovaCommand object, based on its name.  If one exists already,
it is returned.
  */
@@ -796,16 +807,8 @@ BOOL gSplashScreenShown = NO;
             obj = [[NSClassFromString(className) alloc] initWithWebView:webView];
         }
         
-        if ([obj isKindOfClass:[CDVPlugin class]] && [obj respondsToSelector:@selector(setViewController:)])
{ 
-            [obj setViewController:self];
-        }
-        
-        if ([obj isKindOfClass:[CDVPlugin class]] && [obj respondsToSelector:@selector(setCommandDelegate:)])
{ 
-            [obj setCommandDelegate:self.commandDelegate];
-        }
-
-        if (obj != nil) {
-            [self.pluginObjects setObject:obj forKey:className];
+        if (obj != nil && [obj isKindOfClass:[CDVPlugin class]]) {
+            [self registerPlugin:obj withClassName:className];
             [obj release];
         } else {
             NSLog(@"CDVPlugin class %@ (pluginName: %@) does not exist.", className, pluginName);

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/20527867/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 9be7be1..ae4fdf0 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -69,6 +69,10 @@
 		303259C9136B326300982B63 /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef
= 1F92F49E1314023E0046367C /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); };
};
 		303259CA136B326300982B63 /* CDVFileTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef
= C937A4541337599E002C4C79 /* CDVFileTransfer.h */; settings = {ATTRIBUTES = (Public, ); };
};
 		30325A0C136B343700982B63 /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 30325A0B136B343700982B63
/* VERSION */; };
+		3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef
= 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; };
+		3034979D1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef
= 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); };
};
+		3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef
= 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
+		3034979F1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef
= 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
 		3035621714104C34006C2D43 /* CDVWhitelistTests.m in Sources */ = {isa = PBXBuildFile; fileRef
= 30356213141049E1006C2D43 /* CDVWhitelistTests.m */; };
 		30383DE01385F65600E37E22 /* CDVConnection.m in Sources */ = {isa = PBXBuildFile; fileRef
= 307A8F9D1385A2EC00E43782 /* CDVConnection.m */; };
 		30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef
= 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; };
@@ -180,6 +184,8 @@
 		302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4;
lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree
= "<group>"; };
 		303258D8136B2C9400982B63 /* Cordova.framework */ = {isa = PBXFileReference; explicitFileType
= wrapper.cfbundle; includeInIndex = 0; path = Cordova.framework; sourceTree = BUILT_PRODUCTS_DIR;
};
 		30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType
= text; path = VERSION; sourceTree = "<group>"; };
+		3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h;
sourceTree = "<group>"; };
+		3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m;
sourceTree = "<group>"; };
 		30356212141049E1006C2D43 /* CDVWhitelistTests.h */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.h; path = CDVWhitelistTests.h; sourceTree = "<group>";
};
 		30356213141049E1006C2D43 /* CDVWhitelistTests.m */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.objc; path = CDVWhitelistTests.m; sourceTree = "<group>";
};
 		30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding
= 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailability.h; path = Classes/CDVAvailability.h;
sourceTree = "<group>"; };
@@ -382,6 +388,8 @@
 		888700D710922F56009987E8 /* Commands */ = {
 			isa = PBXGroup;
 			children = (
+				3034979A1513D56A0090E688 /* CDVLocalStorage.h */,
+				3034979B1513D56A0090E688 /* CDVLocalStorage.m */,
 				30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */,
 				30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */,
 				30C684921407044A004C1A8E /* CDVURLProtocol.h */,
@@ -503,6 +511,7 @@
 				30F5EBAC14CA26E700987760 /* CDVCommandDelegate.h in Headers */,
 				30392E5014F502C200B9E0B8 /* CDVAvailability.h in Headers */,
 				301F2F2B14F3C9CA003FE9FC /* CDV.h in Headers */,
+				3034979D1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -541,6 +550,7 @@
 				30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */,
 				301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */,
 				30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */,
+				3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -745,6 +755,7 @@
 				30C684831406CB38004C1A8E /* CDVWhitelist.m in Sources */,
 				30C684971407044B004C1A8E /* CDVURLProtocol.m in Sources */,
 				30A90B9414588697006178D3 /* JSONKit.m in Sources */,
+				3034979F1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -790,6 +801,7 @@
 				30A90B9314588697006178D3 /* JSONKit.m in Sources */,
 				8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */,
 				8852C44114B65FD800F0E735 /* CDVCordovaView.m in Sources */,
+				3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};


Mime
View raw message