incubator-callback-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mmo...@apache.org
Subject [2/2] ios commit: [ios] Webstorage backup to cloud/local-only
Date Mon, 22 Oct 2012 19:36:04 GMT
[ios] Webstorage backup to cloud/local-only

LocalStorage and WebSQL databases have been manually backed up in
cordova since iOS5.1 moved them into a Caches directory.  iOS6 adds a
UserDefaults setting to automatically persist these databases, but with
the added feature of backup up to iCloud.

We wanted to allow disabling iCloud backup on iOS6, as well as marking
our manual backups to not be backed up to cloud on iOS5.1.  This patch
changes the BackupWebStorage plist option from a boolean to a 3-option
string: [none, local, cloud].  Toggling between none/local/cloud as well
as upgrading ios versions should work correctly.


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/a39921be
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/a39921be
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/a39921be

Branch: refs/heads/master
Commit: a39921bed239706dc4a0b3a22762d97bc0b2c993
Parents: 78ba908
Author: Michal Mocny <mmocny@gmail.com>
Authored: Mon Oct 22 13:44:03 2012 -0400
Committer: Michal Mocny <mmocny@gmail.com>
Committed: Mon Oct 22 13:44:03 2012 -0400

----------------------------------------------------------------------
 CordovaLib/Classes/CDVLocalStorage.h            |    3 +-
 CordovaLib/Classes/CDVLocalStorage.m            |   89 +++++++++++-------
 CordovaLib/Classes/CDVViewController.m          |   25 +++--
 bin/templates/project/__TESTING__/Cordova.plist |    2 +-
 4 files changed, 71 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a39921be/CordovaLib/Classes/CDVLocalStorage.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocalStorage.h b/CordovaLib/Classes/CDVLocalStorage.h
index 251eb17..e5e3112 100644
--- a/CordovaLib/Classes/CDVLocalStorage.h
+++ b/CordovaLib/Classes/CDVLocalStorage.h
@@ -31,12 +31,11 @@
 - (void)backup:(CDVInvokedUrlCommand*)command;
 - (void)restore:(CDVInvokedUrlCommand*)command;
 
-+ (void)__verifyAndFixDatabaseLocations;
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType;
 // Visible for testing.
 + (BOOL)__verifyAndFixDatabaseLocationsWithAppPlistDict:(NSMutableDictionary*)appPlistDict
     bundlePath                                          :(NSString*)bundlePath
    fileManager                                         :(NSFileManager*)fileManager;
-+ (void)__fixLegacyDatabaseLocationIssues;
 @end
 
 @interface CDVBackupInfo : NSObject

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a39921be/CordovaLib/Classes/CDVLocalStorage.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocalStorage.m b/CordovaLib/Classes/CDVLocalStorage.m
index 7d39052..79e8db7 100644
--- a/CordovaLib/Classes/CDVLocalStorage.m
+++ b/CordovaLib/Classes/CDVLocalStorage.m
@@ -31,21 +31,18 @@
 
 @synthesize backupInfo, webviewDelegate;
 
-- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
+- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings
 {
-    self = (CDVLocalStorage*)[super initWithWebView:theWebView];
+    self = (CDVLocalStorage*)[super initWithWebView:theWebView settings:classSettings];
     if (self) {
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResignActive)
                                                      name:UIApplicationWillResignActiveNotification
object:nil];
 
-        self.backupInfo = [[self class] createBackupInfo];
+        self.backupInfo = [[self class] createBackupInfoWithCloudBackup:((NSString*)[classSettings
objectForKey:@"backupType"] == @"cloud")];
 
         // 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 class] __verifyAndFixDatabaseLocations];
     }
 
     return self;
@@ -54,7 +51,7 @@
 #pragma mark -
 #pragma mark Plugin interface methods
 
-+ (NSMutableArray*)createBackupInfoWithTargetDir:(NSString*)targetDir backupDir:(NSString*)backupDir
rename:(BOOL)rename
++ (NSMutableArray*)createBackupInfoWithTargetDir:(NSString*)targetDir backupDir:(NSString*)backupDir
targetDirNests:(BOOL)targetDirNests backupDirNests:(BOOL)backupDirNests rename:(BOOL)rename
 {
     NSMutableArray* backupInfo = [NSMutableArray arrayWithCapacity:3];
 
@@ -64,8 +61,9 @@
 
     // ////////// LOCALSTORAGE
 
-    original = [targetDir stringByAppendingPathComponent:@"file__0.localstorage"];
-    backup = [backupDir stringByAppendingPathComponent:rename ? @"localstorage.appdata.db":@"file__0.localstorage"];
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/file__0.localstorage":@"file__0.localstorage"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage":@"")];
+    backup = [backupDir stringByAppendingPathComponent:(rename ? @"localstorage.appdata.db":@"file__0.localstorage")];
 
     backupItem = [[CDVBackupInfo alloc] init];
     backupItem.backup = backup;
@@ -76,8 +74,9 @@
 
     // ////////// WEBSQL MAIN DB
 
-    original = [targetDir stringByAppendingPathComponent:@"Databases.db"];
-    backup = [backupDir stringByAppendingPathComponent:rename ? @"websqlmain.appdata.db":@"Databases.db"];
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/Databases/Databases.db":@"Databases.db"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/Databases":@"")];
+    backup = [backupDir stringByAppendingPathComponent:(rename ? @"websqlmain.appdata.db":@"Databases.db")];
 
     backupItem = [[CDVBackupInfo alloc] init];
     backupItem.backup = backup;
@@ -88,8 +87,9 @@
 
     // ////////// WEBSQL DATABASES
 
-    original = [targetDir stringByAppendingPathComponent:@"file__0"];
-    backup = [backupDir stringByAppendingPathComponent:rename ? @"websqldbs.appdata.db":@"file__0"];
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/Databases/file__0":@"file__0"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/Databases":@"")];
+    backup = [backupDir stringByAppendingPathComponent:(rename ? @"websqldbs.appdata.db":@"file__0")];
 
     backupItem = [[CDVBackupInfo alloc] init];
     backupItem.backup = backup;
@@ -101,16 +101,32 @@
     return backupInfo;
 }
 
-+ (NSMutableArray*)createBackupInfo
++ (NSMutableArray*)createBackupInfoWithCloudBackup:(BOOL)cloudBackup
 {
+    // create backup info from backup folder to caches folder
     NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
+    NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
     NSString* cacheFolder = [appLibraryFolder stringByAppendingPathComponent:@"Caches"];
-    NSString* backupsFolder = [appLibraryFolder stringByAppendingPathComponent:@"Backups"];
+    NSString* backupsFolder = [appDocumentsFolder stringByAppendingPathComponent:@"Backups"];
 
-    // create the backups folder
+    // create the backups folder, if needed
     [[NSFileManager defaultManager] createDirectoryAtPath:backupsFolder withIntermediateDirectories:YES
attributes:nil error:nil];
+    [self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:backupsFolder] skip:cloudBackup];
+
+    return [self createBackupInfoWithTargetDir:cacheFolder backupDir:backupsFolder targetDirNests:NO
backupDirNests:NO rename:YES];
+}
 
-    return [self createBackupInfoWithTargetDir:cacheFolder backupDir:backupsFolder rename:YES];
++ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL*)URL skip:(BOOL)skip
+{
+    assert(IsAtLeastiOSVersion(@"5.1"));
+    assert([[NSFileManager defaultManager] fileExistsAtPath:[URL path]]);
+
+    NSError* error = nil;
+    BOOL success = [URL setResourceValue:[NSNumber numberWithBool:skip] forKey:NSURLIsExcludedFromBackupKey
error:&error];
+    if (!success) {
+        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
+    }
+    return success;
 }
 
 + (BOOL)copyFrom:(NSString*)src to:(NSString*)dest error:(NSError * __autoreleasing*)error
@@ -252,6 +268,12 @@
     }
 }
 
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType
+{
+    [self __verifyAndFixDatabaseLocations];
+    [self __restoreLegacyDatabaseLocationsWithBackupType:backupType];
+}
+
 + (void)__verifyAndFixDatabaseLocations
 {
     NSBundle* mainBundle = [NSBundle mainBundle];
@@ -303,31 +325,26 @@
     return dirty;
 }
 
-+ (void)__fixLegacyDatabaseLocationIssues
++ (void)__restoreLegacyDatabaseLocationsWithBackupType:(NSString*)backupType
 {
-    if (IsAtLeastiOSVersion(@"6.0")) {
-        // Ensure that the webview does not backup the databases to iCloud (We set to this
true in 2.1, so need to reset it for upgraders).
-        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitStoreWebDataForBackup"];
+    // on iOS 6, if you toggle between cloud/local backup, you must move database locations.
 Default upgrade from iOS5.1 to iOS6 is like a toggle from local to cloud.
+    if (!IsAtLeastiOSVersion(@"6.0")) {
+        return;
     }
 
-    /*
-     * There are currently two legacy storage locations:
-     *   {Lib}/WebKit/LocalStorage which was used for store database (without backup renaming)
in ios <5.1 and briefly for ios6, and
-     *   {Doc}/Backups which was used to store database backups (with backup renaming) with
ios5.1+ until Apple started rejecting apps
-     *      for using the {Doc} folder to save non user generated content.
-     */
     NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
     NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
 
-    // targetDir is where we want our databases to end up
-    NSString* targetDir = [appLibraryFolder stringByAppendingPathComponent:@"Caches"];
-
-    // backupDir's are the places where we may find old legacy backups
-    NSString* backupDir = [appDocumentsFolder stringByAppendingPathComponent:@"Backups"];
-    NSString* backupDir2 = [appLibraryFolder stringByAppendingPathComponent:@"WebKit/LocalStorage"];
+    NSMutableArray* backupInfo = nil;
 
-    NSMutableArray* backupInfo = [self createBackupInfoWithTargetDir:targetDir backupDir:backupDir
rename:YES];
-    [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:targetDir backupDir:backupDir2
rename:NO]];
+    if ([backupType isEqualToString:@"cloud"]) {
+        // We would like to restore old backups/caches databases to the new destination (nested
in lib folder)
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder
backupDir:[appDocumentsFolder stringByAppendingPathComponent:@"Backups"] targetDirNests:YES
backupDirNests:NO rename:YES]];
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder
backupDir:[appLibraryFolder stringByAppendingPathComponent:@"Caches"] targetDirNests:YES backupDirNests:NO
rename:NO]];
+    } else {
+        assert([backupType isEqualToString:@"local"]);
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:[appLibraryFolder
stringByAppendingPathComponent:@"Caches"] backupDir:appLibraryFolder targetDirNests:NO backupDirNests:YES
rename:NO]];
+    }
 
     NSFileManager* manager = [NSFileManager defaultManager];
 
@@ -341,6 +358,8 @@
             [manager removeItemAtPath:info.backup error:nil];
         }
     }
+
+    [[NSUserDefaults standardUserDefaults] setBool:(backupType == @"cloud") forKey:@"WebKitStoreWebDataForBackup"];
 }
 
 #pragma mark -

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a39921be/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index 987ecee..c1648d9 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -175,16 +175,19 @@
 
     // // Fix the iOS 5.1 SECURITY_ERR bug (CB-347), this must be before the webView is instantiated
////
 
-    BOOL backupWebStorage = YES;  // default value
-    if ([self.settings objectForKey:@"BackupWebStorage"]) {
-        backupWebStorage = [(NSNumber*)[settings objectForKey:@"BackupWebStorage"] boolValue];
-    }
+    NSString* backupWebStorageType = @"cloud"; // default value
 
-    if (backupWebStorage) {
-        [CDVLocalStorage __verifyAndFixDatabaseLocations];
+    id backupWebStorage = [self.settings objectForKey:@"BackupWebStorage"];
+    if ([backupWebStorage isKindOfClass:[NSString class]]) {
+        backupWebStorageType = backupWebStorage;
+    } else if ([backupWebStorage isKindOfClass:[NSNumber class]]) {
+        backupWebStorageType = [(NSNumber*) backupWebStorage boolValue] ? @"cloud" : @"none";
     }
+    NSLog(@"BackupType: %@", backupWebStorageType);
 
-    [CDVLocalStorage __fixLegacyDatabaseLocationIssues];
+    if (IsAtLeastiOSVersion(@"5.1")) {
+        [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType];
+    }
 
     // // Instantiate the WebView ///////////////
 
@@ -211,10 +214,12 @@
     }
 
     /*
-     * Fire up CDVLocalStorage on iOS 5.1+ to work-around WebKit storage limitations
+     * Fire up CDVLocalStorage to work-around WebKit storage limitations: on all iOS 5.1+
versions for local-only backups, but only needed on iOS 5.1 for cloud backup.
      */
-    if (IsAtLeastiOSVersion(@"5.1") && backupWebStorage) {
-        [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage
class])];
+    if (IsAtLeastiOSVersion(@"5.1") && (([backupWebStorage isEqualToString:@"local"])
||
+            ([backupWebStorage isEqualToString:@"cloud"] && !IsAtLeastiOSVersion(@"6.0"))))
{
+        [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView settings:[NSDictionary
dictionaryWithObjectsAndKeys:
+                    @"backupType", backupWebStorageType, nil]] withClassName:NSStringFromClass([CDVLocalStorage
class])];
     }
 
     /*

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a39921be/bin/templates/project/__TESTING__/Cordova.plist
----------------------------------------------------------------------
diff --git a/bin/templates/project/__TESTING__/Cordova.plist b/bin/templates/project/__TESTING__/Cordova.plist
index 54892bc..2c92742 100644
--- a/bin/templates/project/__TESTING__/Cordova.plist
+++ b/bin/templates/project/__TESTING__/Cordova.plist
@@ -45,7 +45,7 @@
 	<key>OpenAllWhitelistURLsInWebView</key>
 	<false/>
 	<key>BackupWebStorage</key>
-	<true/>
+	<string>gray</string>
 	<key>ExternalHosts</key>
 	<array/>
 	<key>Plugins</key>


Mime
View raw message