Apache Cordova
  1. Apache Cordova
  2. CB-330

localStorage / SQLDatabase no longer persistent after iOS 5.01 Update

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: 1.3.0, 1.4.0, 1.5.0
    • Fix Version/s: 1.6.0
    • Component/s: iOS
    • Environment:

      iOS 5.01
      PhoneGap (Any version)
      Xcode 4
      Build.PhoneGap

      Description

      Dear Dev

      WebKit data (localstorage or local SQLite) are now stored in Library/ Caches folder (instead of Library/WebKit folder). This is a big problem for all apps using UIWebView and storing user data, because they will no longer be backed up and may be deleted. There are a lot of apps using localstorage or SQLite as a critical feature.

      The SQLite database gets deleted because the database is saved in a location on the filesystem which Apple does not consider to contain persistent data.

      Steps to Reproduce:

      In a UIWebView, create a new DB or use localStorage with JavaScript.
      You can see that the WebKit data is now stored in Library/Caches :

      Expected Results:

      We should at least specify the directory of WebKit data (and to set it
      to Documents/ for critical data)

      Actual Results:

      The WebKit data are stored in Library/Caches folder, and can be
      deleted

      Regression:
      To migrate database location from Library/Caches to some other location such as Documents.


      Ref: http://developer.apple.com/icloud/documentation/data-storage/
      https://devforums.apple.com/thread/137882?start=0&tstart=0

      1. CDVLocalStorageDiagnostics.zip
        4 kB
        Shazron Abdullah
      2. CDVLocalStoragePlugin.zip
        20 kB
        Shazron Abdullah
      3. Directory-Structure-CB-330.zip
        452 kB
        Shazron Abdullah
      4. iOS WebKit Database Locations.txt
        0.6 kB
        Shazron Abdullah
      5. LocalStorageTest.zip
        904 kB
        Amirudin Bin Mohamed Ghani
      6. README.txt
        5 kB
        Shazron Abdullah

        Issue Links

          Activity

          Hide
          Henkjan de Bruin added a comment -

          This is definitely a big problem. It's in iOS 5.1 as well. A patch would be highly appreciated.

          Show
          Henkjan de Bruin added a comment - This is definitely a big problem. It's in iOS 5.1 as well. A patch would be highly appreciated.
          Hide
          Siep de Vries added a comment -

          This also is a serious issue for some applications we developed. A patch would indeed be highly appreciated.

          Show
          Siep de Vries added a comment - This also is a serious issue for some applications we developed. A patch would indeed be highly appreciated.
          Hide
          Shazron Abdullah added a comment -

          I'm going to add a core plugin to handle this issue.

          Show
          Shazron Abdullah added a comment - I'm going to add a core plugin to handle this issue.
          Hide
          Shazron Abdullah added a comment -

          Right now it's in my branch "localstorage-plugin". Commit here: https://github.com/shazron/incubator-cordova-ios/commit/e726026c0f859b2e6cfe2cd4f93a4c3602f57fab

          Show
          Shazron Abdullah added a comment - Right now it's in my branch "localstorage-plugin". Commit here: https://github.com/shazron/incubator-cordova-ios/commit/e726026c0f859b2e6cfe2cd4f93a4c3602f57fab
          Hide
          Shazron Abdullah added a comment -

          The plugin is attached, with instructions for PhoneGap versions <= 1.4.1, and a separate one for 1.5.0 only. In 1.6.0 (coming in a couple of weeks), this will already be included.

          Please test and let me know any feedback.

          Show
          Shazron Abdullah added a comment - The plugin is attached, with instructions for PhoneGap versions <= 1.4.1, and a separate one for 1.5.0 only. In 1.6.0 (coming in a couple of weeks), this will already be included. Please test and let me know any feedback.
          Hide
          Shazron Abdullah added a comment -

          Fixed copy and paste error.

          Show
          Shazron Abdullah added a comment - Fixed copy and paste error.
          Hide
          Shazron Abdullah added a comment -

          Note: initially in a fresh app the Webkit db is not created yet until you use localStorage at least once, so on startup you might see a "file not exists" error which is normal

          Show
          Shazron Abdullah added a comment - Note: initially in a fresh app the Webkit db is not created yet until you use localStorage at least once, so on startup you might see a "file not exists" error which is normal
          Hide
          Amirudin Bin Mohamed Ghani added a comment -

          Hey Shaz

          Thanks for the plugin. Will have a test and let you know.

          Show
          Amirudin Bin Mohamed Ghani added a comment - Hey Shaz Thanks for the plugin. Will have a test and let you know.
          Hide
          Amirudin Bin Mohamed Ghani added a comment - - edited

          The Plugin doesn't work for me. The error "file not exists" continuously exist and backup command doesn't move database to different location. Please refer my sample code above: LocalStorageTest.zip

          Environment:
          iOS 5.1
          XCode 4.3.1

          Show
          Amirudin Bin Mohamed Ghani added a comment - - edited The Plugin doesn't work for me. The error "file not exists" continuously exist and backup command doesn't move database to different location. Please refer my sample code above: LocalStorageTest.zip Environment: iOS 5.1 XCode 4.3.1
          Hide
          Shazron Abdullah added a comment -

          Thanks - I'll check on this tomorrow. Can you try testing using localStorage - that should work. Please attach your error log as well for me to verify that I am getting the same error results.

          Show
          Shazron Abdullah added a comment - Thanks - I'll check on this tomorrow. Can you try testing using localStorage - that should work. Please attach your error log as well for me to verify that I am getting the same error results.
          Hide
          Luther Goh Lu Feng added a comment - - edited

          This does not seem to work for me. I am using localStorage. May I know how I can echo out the webkit data location?

          Env:
          Phonegap 1.4.0
          iOS 5.1
          XCode 4.2

          Show
          Luther Goh Lu Feng added a comment - - edited This does not seem to work for me. I am using localStorage. May I know how I can echo out the webkit data location? Env: Phonegap 1.4.0 iOS 5.1 XCode 4.2
          Hide
          Luther Goh Lu Feng added a comment -

          A friend shared this with me. I am sharing it just in case it is useful.

          Show
          Luther Goh Lu Feng added a comment - A friend shared this with me. I am sharing it just in case it is useful.
          Hide
          Urs Zimmermann added a comment -

          Does this handle existing databases like in https://issues.apache.org/jira/browse/CB-347?

          Show
          Urs Zimmermann added a comment - Does this handle existing databases like in https://issues.apache.org/jira/browse/CB-347?
          Hide
          Amirudin Bin Mohamed Ghani added a comment -

          Hi Shaz

          I have no luck here. Both SQLDatabase(LocalStorageTest.zip) and localStorage(LocalStorageTest2.zip) produce the same result. See my sample app for localStorage : LocalStorageTest2.zip

          Error:
          2012-03-20 00:21:04.260 LocalStorageTest[724:13403] Error in CDVLocalStorage restore: /Users/amirudinmohamedghani/Library/Application Support/iPhone Simulator/5.1/Applications/5163E6F0-8988-403F-8807-03766BA3C1F1/Documents/appdata.db file does not exist.

          Env:
          iOS 5.1
          Xcode 4.3.1
          PhoneGap 1.4.1
          Running on Simulator several times.

          Show
          Amirudin Bin Mohamed Ghani added a comment - Hi Shaz I have no luck here. Both SQLDatabase(LocalStorageTest.zip) and localStorage(LocalStorageTest2.zip) produce the same result. See my sample app for localStorage : LocalStorageTest2.zip Error: 2012-03-20 00:21:04.260 LocalStorageTest [724:13403] Error in CDVLocalStorage restore: /Users/amirudinmohamedghani/Library/Application Support/iPhone Simulator/5.1/Applications/5163E6F0-8988-403F-8807-03766BA3C1F1/Documents/appdata.db file does not exist. Env: iOS 5.1 Xcode 4.3.1 PhoneGap 1.4.1 Running on Simulator several times.
          Hide
          Shazron Abdullah added a comment -

          @Urs Zimmerman - there's a separate fix for that one, but the fix will be included in the same plugin.

          Show
          Shazron Abdullah added a comment - @Urs Zimmerman - there's a separate fix for that one, but the fix will be included in the same plugin.
          Hide
          Shazron Abdullah added a comment -

          I see what's going on. I was handling it for the localStorage case (and it works, according to my testing, with localStorage only. See my comment earlier about path not exists only for the first time).

          WebSQL puts the db into another structure. I've done some testing, and listed the directory structures that I need to handle in the plugin. I've attached the screenshots.

          Show
          Shazron Abdullah added a comment - I see what's going on. I was handling it for the localStorage case (and it works, according to my testing, with localStorage only. See my comment earlier about path not exists only for the first time). WebSQL puts the db into another structure. I've done some testing, and listed the directory structures that I need to handle in the plugin. I've attached the screenshots.
          Hide
          Shazron Abdullah added a comment -

          iOS WebKit Database Locations

          "~" signifies the application's folder.

          window.localStorage (4.3)

          1. ~/Library/WebKit/LocalStorage/file__0.localstorage

          window.localStorage (5.1)

          1. ~/Library/Caches/file__0.localstorage

          WebSQL (4.3)

          1. ~/Library/WebKit/Databases/Databases.db
          2. ~/Library/WebKit/Databases/file__0/*.db (each database creates one file here)

          WebSQL (5.1)

          1. ~/Library/Caches/Databases.db
          2. ~/Library/Caches/file__0/*.db (each database creates one file here)

          Show
          Shazron Abdullah added a comment - iOS WebKit Database Locations "~" signifies the application's folder. window.localStorage (4.3) 1. ~/Library/WebKit/LocalStorage/file__0.localstorage window.localStorage (5.1) 1. ~/Library/Caches/file__0.localstorage WebSQL (4.3) 1. ~/Library/WebKit/Databases/Databases.db 2. ~/Library/WebKit/Databases/file__0/*.db (each database creates one file here) WebSQL (5.1) 1. ~/Library/Caches/Databases.db 2. ~/Library/Caches/file__0/*.db (each database creates one file here)
          Hide
          Samuel Michelot added a comment -

          Thanks Shazron for working on this bug !

          Just a question: this plugin change the working location of WebKit localstorage files, or it just regularly backup the files with a copy inside the Document folder ?

          Show
          Samuel Michelot added a comment - Thanks Shazron for working on this bug ! Just a question: this plugin change the working location of WebKit localstorage files, or it just regularly backup the files with a copy inside the Document folder ?
          Hide
          Shazron Abdullah added a comment -

          @Samuel it should do both

          Show
          Shazron Abdullah added a comment - @Samuel it should do both
          Hide
          Emile khattar added a comment -

          is there any "step by step" list on how to apply the fix to an existing phonegap project (PG not CDV) ?

          Thanks Shazron

          Show
          Emile khattar added a comment - is there any "step by step" list on how to apply the fix to an existing phonegap project (PG not CDV) ? Thanks Shazron
          Hide
          Shazron Abdullah added a comment -

          The package has a README.txt with instructions for all PG/CDV versions.

          Show
          Shazron Abdullah added a comment - The package has a README.txt with instructions for all PG/CDV versions.
          Hide
          Emile khattar added a comment -

          Oopps i just saw it great
          I will post my feedback soon

          Show
          Emile khattar added a comment - Oopps i just saw it great I will post my feedback soon
          Hide
          Shazron Abdullah added a comment -

          Attached the latest version of the plugin. Backs up both the localStorage and WebSQL databases, and fixes CB-347.

          Note that on a new install and first run, it will try to restore a non-existent backup, this is normal.

          Show
          Shazron Abdullah added a comment - Attached the latest version of the plugin. Backs up both the localStorage and WebSQL databases, and fixes CB-347 . Note that on a new install and first run, it will try to restore a non-existent backup, this is normal.
          Hide
          Emile khattar added a comment -

          I got this when running the analyzer
          http://imgur.com/HwISY

          Show
          Emile khattar added a comment - I got this when running the analyzer http://imgur.com/HwISY
          Hide
          Shazron Abdullah added a comment -

          @Emile thanks - didn't run the analyzer on the plugin. I'll clean up these issues

          Show
          Shazron Abdullah added a comment - @Emile thanks - didn't run the analyzer on the plugin. I'll clean up these issues
          Hide
          Emile khattar added a comment -

          alright thanks

          I downloaded the 5.1 sdk but i am not having any issue using the simulator even without the plugin no problem
          is this issue only on devices ?

          Show
          Emile khattar added a comment - alright thanks I downloaded the 5.1 sdk but i am not having any issue using the simulator even without the plugin no problem is this issue only on devices ?
          Hide
          Shazron Abdullah added a comment -

          @Emile This is about persistence (try to read the original description again). The location of the databases are in Library/Caches which is not guaranteed to be be there in the case of an app upgrade, or iOS system cleanup (as per Apple rules). Previously it was guaranteed since it was in Library/WebKit.

          Show
          Shazron Abdullah added a comment - @Emile This is about persistence (try to read the original description again). The location of the databases are in Library/Caches which is not guaranteed to be be there in the case of an app upgrade, or iOS system cleanup (as per Apple rules). Previously it was guaranteed since it was in Library/WebKit.
          Hide
          Emile khattar added a comment -

          ok clear

          Show
          Emile khattar added a comment - ok clear
          Hide
          Edgar Canas added a comment -

          Shazron, just wondering as to why the solution is only doing a copy instead of actually building a native client similar to: https://github.com/davibe/Phonegap-SQLitePlugin

          Unless I missed something the solution above only does a backup and restore?

          The problem with doing a backup and restore is that well you can loose data depending of when a backup is done, a better solution would be to run the database right from the documents folder similar, this way you don't need to do any backups and you are certain you will always get the latest file. The native client plugin seems to work fine except for null values.

          Can we get native DB support into Cordova instead of having to worry to when to do backups and restores?

          Show
          Edgar Canas added a comment - Shazron, just wondering as to why the solution is only doing a copy instead of actually building a native client similar to: https://github.com/davibe/Phonegap-SQLitePlugin Unless I missed something the solution above only does a backup and restore? The problem with doing a backup and restore is that well you can loose data depending of when a backup is done, a better solution would be to run the database right from the documents folder similar, this way you don't need to do any backups and you are certain you will always get the latest file. The native client plugin seems to work fine except for null values. Can we get native DB support into Cordova instead of having to worry to when to do backups and restores?
          Hide
          Shazron Abdullah added a comment -

          @Edgar native db support is a good idea, please file a feature request - since all platforms will need to support this, and we need to have a discussion between all devs for this new feature.

          The time to the next version being out (Mar 26th) is short, and adding a whole new feature that people depend on, is not a trivial effort. This fix is for people that need to get this fixed immediately (those that have apps already in the App Store and users are already complaining). That's why I took the time to make this a plugin that previous versions of Cordova could use as well.

          This method does not lose data - if you see where the backup is done in the code, it is done on app pause and terminate, and is synchronous.

          Show
          Shazron Abdullah added a comment - @Edgar native db support is a good idea, please file a feature request - since all platforms will need to support this, and we need to have a discussion between all devs for this new feature. The time to the next version being out (Mar 26th) is short, and adding a whole new feature that people depend on, is not a trivial effort. This fix is for people that need to get this fixed immediately (those that have apps already in the App Store and users are already complaining). That's why I took the time to make this a plugin that previous versions of Cordova could use as well. This method does not lose data - if you see where the backup is done in the code, it is done on app pause and terminate, and is synchronous.
          Hide
          Emile khattar added a comment -

          @shazron, localStorage is being deleted/not recovered when we manually kill the app
          any idea?

          Show
          Emile khattar added a comment - @shazron, localStorage is being deleted/not recovered when we manually kill the app any idea?
          Hide
          Edgar Canas added a comment -

          @Shazron, new to this.. where do I file a feature request?

          Yes the solution you have works as a intermediate, problem is as Emile mentioned if the app is killed manually or even if the app dies or resets for whatever reason you will loose whatever data you had done before the last backup, since a backup will only be done when the apps gets closed/reopened. Any type or reset that being soft or app reset it will overwrite the exiting data with the previous backup, which is not a desired option. Is there a way you can update the app so that it checks for modify time or something before the data gets overwritten with an outdated backup?

          The other option that I was looking at is to do a backup after every transaction but my database is around 7-20mb so not sure how efficient/quick would be do do frequent backups after any database change.

          Show
          Edgar Canas added a comment - @Shazron, new to this.. where do I file a feature request? Yes the solution you have works as a intermediate, problem is as Emile mentioned if the app is killed manually or even if the app dies or resets for whatever reason you will loose whatever data you had done before the last backup, since a backup will only be done when the apps gets closed/reopened. Any type or reset that being soft or app reset it will overwrite the exiting data with the previous backup, which is not a desired option. Is there a way you can update the app so that it checks for modify time or something before the data gets overwritten with an outdated backup? The other option that I was looking at is to do a backup after every transaction but my database is around 7-20mb so not sure how efficient/quick would be do do frequent backups after any database change.
          Hide
          Emile khattar added a comment -

          i am not sure if onResignActive and onAppTerminate are being fire when the app is killed by the kernel or manually by the user.
          We need to have a look at the apple docs. Unfortunately i don't have an ios5.1 device in my hand to do more tracing, and on the simulator i can't reproduce

          Show
          Emile khattar added a comment - i am not sure if onResignActive and onAppTerminate are being fire when the app is killed by the kernel or manually by the user. We need to have a look at the apple docs. Unfortunately i don't have an ios5.1 device in my hand to do more tracing, and on the simulator i can't reproduce
          Hide
          Edgar Canas added a comment -

          verifyAndFixDatabaseLocations works but it requires the app to be closed via task manager then opened up again. Otherwise on the first try it will fail to load the database.

          Show
          Edgar Canas added a comment - verifyAndFixDatabaseLocations works but it requires the app to be closed via task manager then opened up again. Otherwise on the first try it will fail to load the database.
          Hide
          Emile khattar added a comment - - edited

          @shazron i am sorry i accidentally realized that i called the plugin on "didFailLoadWithError" hehe i fixed it now tomorrow i will test and let you know.

          @edgar what about other cases like crashes or mobile reboot ...

          Show
          Emile khattar added a comment - - edited @shazron i am sorry i accidentally realized that i called the plugin on "didFailLoadWithError" hehe i fixed it now tomorrow i will test and let you know. @edgar what about other cases like crashes or mobile reboot ...
          Hide
          Emile khattar added a comment -

          @edgar, if you read the code of the plugin you will see that logically no data should be lost at all.

          // onAppTerminate is fired on UIApplicationWillTerminateNotification
          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil];

          http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationWillTerminate:
          This method lets your application know that it is about to be terminated and purged from memory entirely. You should use this method to perform any final clean-up tasks for your application, such as freeing shared resources, saving user data, invalidating timers, and storing enough application state to reconstitute your application’s interface when it is relaunched. Your implementation of this method has approximately five seconds to perform any tasks and return. If the method does not return before time expires, the system may kill the process altogether.

          five seconds should be enough i think

          So in theory this fixed should be good to support people who are using localStorage and Sql storage.
          And the problem i had should be to the error i did by placing the plugin call in the wrong place.

          However i agree with you having some sort of a "natural" persistent storage

          thanks everyone

          Show
          Emile khattar added a comment - @edgar, if you read the code of the plugin you will see that logically no data should be lost at all. // onAppTerminate is fired on UIApplicationWillTerminateNotification [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil]; http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationWillTerminate: This method lets your application know that it is about to be terminated and purged from memory entirely. You should use this method to perform any final clean-up tasks for your application, such as freeing shared resources, saving user data, invalidating timers, and storing enough application state to reconstitute your application’s interface when it is relaunched. Your implementation of this method has approximately five seconds to perform any tasks and return. If the method does not return before time expires, the system may kill the process altogether. five seconds should be enough i think So in theory this fixed should be good to support people who are using localStorage and Sql storage. And the problem i had should be to the error i did by placing the plugin call in the wrong place. However i agree with you having some sort of a "natural" persistent storage thanks everyone
          Hide
          Shazron Abdullah added a comment - - edited

          @edgar You have a valid point regarding intermediate changes (the manual app terminate scenario - then clobbering of the existing database with latest changes with older backed up data on next startup), I'll work a fix in to mitigate this risk. To create a feature request, on the top right of jira, there is a "Create Issue" button - then you choose the "Issue Type" as "New Feature". Make sure you add the right "components" (platforms) that you desire the feature to be in.

          To further mitigate this risk - I can add callbacks in the backup and restore functions, so if you choose to periodically backup - you can wait for the callbacks to return before continuing.

          Show
          Shazron Abdullah added a comment - - edited @edgar You have a valid point regarding intermediate changes (the manual app terminate scenario - then clobbering of the existing database with latest changes with older backed up data on next startup), I'll work a fix in to mitigate this risk. To create a feature request, on the top right of jira, there is a "Create Issue" button - then you choose the "Issue Type" as "New Feature". Make sure you add the right "components" (platforms) that you desire the feature to be in. To further mitigate this risk - I can add callbacks in the backup and restore functions, so if you choose to periodically backup - you can wait for the callbacks to return before continuing.
          Hide
          Shazron Abdullah added a comment -

          @edgar verifyAndFixDatabaseLocations is for a separate issue CB-347, and it would (and should) only run at startup anyway and it does - it runs before the webview loads and calls any javascript.

          Show
          Shazron Abdullah added a comment - @edgar verifyAndFixDatabaseLocations is for a separate issue CB-347 , and it would (and should) only run at startup anyway and it does - it runs before the webview loads and calls any javascript.
          Hide
          Emile khattar added a comment - - edited

          http://pastebin.com/4VCnTuyA is this normal?

          @shazron, so this plugin doesn't cover all the cases that the localStorage was covering naturally?

          Show
          Emile khattar added a comment - - edited http://pastebin.com/4VCnTuyA is this normal? @shazron, so this plugin doesn't cover all the cases that the localStorage was covering naturally?
          Hide
          Shazron Abdullah added a comment -

          @emile - it's normal, since you never created any WebSQL databases, those files were not created. I've got to clean the error logging up so it's not as verbose. This plugin is just a backup and restore system (I still don't think you know what this bug is about?), plus the fix for CB-347.

          Show
          Shazron Abdullah added a comment - @emile - it's normal, since you never created any WebSQL databases, those files were not created. I've got to clean the error logging up so it's not as verbose. This plugin is just a backup and restore system (I still don't think you know what this bug is about?), plus the fix for CB-347 .
          Hide
          Emile khattar added a comment -

          that's what i thought, but i read Error not warning so i asked.
          I fully aware what the bug is about, and what does this plugin do. But i find it a hassle to backup every-time i modify the localStorage.

          let me have a look @CB-347

          Show
          Emile khattar added a comment - that's what i thought, but i read Error not warning so i asked. I fully aware what the bug is about, and what does this plugin do. But i find it a hassle to backup every-time i modify the localStorage. let me have a look @ CB-347
          Hide
          Emile khattar added a comment -

          OK, i see cb347 is what verifyAndFixDatabaseLocations is doing.
          So we still have the case when the user kills the app from the task manager, since onAppTerminate and onResignActive are not being called.
          So i am thinking of backuping up everytime the localStorage is modified. Unless you propose a better fix.

          Thanks

          Show
          Emile khattar added a comment - OK, i see cb347 is what verifyAndFixDatabaseLocations is doing. So we still have the case when the user kills the app from the task manager, since onAppTerminate and onResignActive are not being called. So i am thinking of backuping up everytime the localStorage is modified. Unless you propose a better fix. Thanks
          Hide
          Emile khattar added a comment -

          Actually i think no need to manually backup at all since the user can't close the application from the task manager before it resignActive, so the intermediate changes will stored.

          Show
          Emile khattar added a comment - Actually i think no need to manually backup at all since the user can't close the application from the task manager before it resignActive, so the intermediate changes will stored.
          Hide
          Samuel Michelot added a comment - - edited

          After some testing, it looks like the plugin doesn't do the migration from WebKit folder to the Caches folder. It should happens when users upgrade to iOS5.1 before that fix (before upgrading the app with the backup fix). I know that sometime, the WebKit folder is completely deleted during the iOS 5.1 update, but sometime, it's still there...

          Here is an example of code to handle that migration : https://gist.github.com/2009491 (just for inspiration, because it migrate everything to the Document folder, it's for the PGSQLitePlugin)

          Show
          Samuel Michelot added a comment - - edited After some testing, it looks like the plugin doesn't do the migration from WebKit folder to the Caches folder. It should happens when users upgrade to iOS5.1 before that fix (before upgrading the app with the backup fix). I know that sometime, the WebKit folder is completely deleted during the iOS 5.1 update, but sometime, it's still there... Here is an example of code to handle that migration : https://gist.github.com/2009491 (just for inspiration, because it migrate everything to the Document folder, it's for the PGSQLitePlugin)
          Hide
          Daniel added a comment -

          I still have issues with this plugin when running in the iOS 5.1 simulator.

          I perform the following steps:

          1. Start application with plugin installed
          2. Create data into localstorage
          3. Double press home button (now the task manager comes up with nothing in it)
          4. Single press home button (we are taken back to the springboard, while application is still running in the background)
          5. Double press home button (now the task manager comes up with the application running)
          6. Hold the icon of the app and force it to close
          7. Start the application again.

          At this moment all data from localstorage is still present. Now I add extra data and i repeat steps 3,4,5,6,7

          After two or three times you will see the message "Program ended with exit code: 0" in your debug log and the debugger disconnected from the process.

          If I again add some new data and repeat steps 3,4,5,6,7 the newly created data is gone when the application at step 7.

          Anyone else who is also able to reproduce the same?

          Show
          Daniel added a comment - I still have issues with this plugin when running in the iOS 5.1 simulator. I perform the following steps: 1. Start application with plugin installed 2. Create data into localstorage 3. Double press home button (now the task manager comes up with nothing in it) 4. Single press home button (we are taken back to the springboard, while application is still running in the background) 5. Double press home button (now the task manager comes up with the application running) 6. Hold the icon of the app and force it to close 7. Start the application again. At this moment all data from localstorage is still present. Now I add extra data and i repeat steps 3,4,5,6,7 After two or three times you will see the message "Program ended with exit code: 0" in your debug log and the debugger disconnected from the process. If I again add some new data and repeat steps 3,4,5,6,7 the newly created data is gone when the application at step 7. Anyone else who is also able to reproduce the same?
          Hide
          Shazron Abdullah added a comment -

          hi everyone - I'm off today and I will look at your test results tomorrow.

          Show
          Shazron Abdullah added a comment - hi everyone - I'm off today and I will look at your test results tomorrow.
          Hide
          Emile khattar added a comment -

          explicit backup calls after setItem solved all my problems

          @shazron have a nice day off and thanks

          Cheers

          Show
          Emile khattar added a comment - explicit backup calls after setItem solved all my problems @shazron have a nice day off and thanks Cheers
          Hide
          Yoh Suzuki added a comment - - edited

          The plugin appears to be working correctly for me, but when I install over top on the phone (i.e. do an ad-hoc update, even with the same build), I don't have anything in localStorage the very next time the app is started. Closing the program immediately and relaunching it gives me what I previously had in localStorage. This does not happen with an older iOS.

          @shazron – you mentioned that "on a new install and first run, it will try to restore a non-existent backup, this is normal." Will this be fixed? This leaves localStorage unreliable.

          Show
          Yoh Suzuki added a comment - - edited The plugin appears to be working correctly for me, but when I install over top on the phone (i.e. do an ad-hoc update, even with the same build), I don't have anything in localStorage the very next time the app is started. Closing the program immediately and relaunching it gives me what I previously had in localStorage. This does not happen with an older iOS. @shazron – you mentioned that "on a new install and first run, it will try to restore a non-existent backup, this is normal." Will this be fixed? This leaves localStorage unreliable.
          Hide
          Emile khattar added a comment - - edited

          @Yoh are you calling PhoneGap.exec(null, null, "CDVLocalStorage", "backup", []); anytime you modify the localStorage?

          @Yoh i did the same scenario you are discribing and yes no localStorage restored for some reason.

          Show
          Emile khattar added a comment - - edited @Yoh are you calling PhoneGap.exec(null, null, "CDVLocalStorage", "backup", []); anytime you modify the localStorage? @Yoh i did the same scenario you are discribing and yes no localStorage restored for some reason.
          Hide
          Daniel added a comment -

          Would it be possible to programmatically modify the localstorage location? This would be a perfect solutions for applications that do not need to worry about migrating data from previous locations (which is the case for my project).

          Show
          Daniel added a comment - Would it be possible to programmatically modify the localstorage location? This would be a perfect solutions for applications that do not need to worry about migrating data from previous locations (which is the case for my project).
          Hide
          Brad Lackey added a comment -

          I'm having the same issue as @Yoh and would be very interested to know if anyone is able to upgrade / install on top of a current build and see the settings from your previous installation (without having to close and re-open again).

          Show
          Brad Lackey added a comment - I'm having the same issue as @Yoh and would be very interested to know if anyone is able to upgrade / install on top of a current build and see the settings from your previous installation (without having to close and re-open again).
          Hide
          Yoh Suzuki added a comment - - edited

          @emile - I am not calling Cordova.exec(null, null, "CDVLocalStorage", "backup", []); (for 1.5.0) from JavaScript because backup is called in native code in onResignActive and onAppTerminate. Setting breakpoints in Xcode confirms this. (I believe calling it from JavaScript is an option for those who don't want change AppDelegate.m in steps 4 and 5 of the plugin installation instructions.)

          Show
          Yoh Suzuki added a comment - - edited @emile - I am not calling Cordova.exec(null, null, "CDVLocalStorage", "backup", []); (for 1.5.0) from JavaScript because backup is called in native code in onResignActive and onAppTerminate. Setting breakpoints in Xcode confirms this. (I believe calling it from JavaScript is an option for those who don't want change AppDelegate.m in steps 4 and 5 of the plugin installation instructions.)
          Hide
          Emile khattar added a comment - - edited

          @Yoh you are right the plugin is meant to backup when the app resignActive or beingClosed by the OS.
          However you need explicitly backup after you call setItem or window.localStorage.foo=bar to support cases like when the users kill the app manually from the task manager, or when the user turn OFF/ON the phone, or maybe when the mobile turns off for whatever reason without a backup.

          I would suggest you implement something function mySetIem (bar)

          { // window.localeStorage.foo = bar; // backup: Cordova.exec(null, null, "CDVLocalStorage", "backup", []); }

          this will allow your storage to be more robust exept for the cases that you and @Brad hilighted, when we install on top of exsisting app,

          Let's wait for @shazron to advise so we don't waste time.

          Show
          Emile khattar added a comment - - edited @Yoh you are right the plugin is meant to backup when the app resignActive or beingClosed by the OS. However you need explicitly backup after you call setItem or window.localStorage.foo=bar to support cases like when the users kill the app manually from the task manager, or when the user turn OFF/ON the phone, or maybe when the mobile turns off for whatever reason without a backup. I would suggest you implement something function mySetIem (bar) { // window.localeStorage.foo = bar; // backup: Cordova.exec(null, null, "CDVLocalStorage", "backup", []); } this will allow your storage to be more robust exept for the cases that you and @Brad hilighted, when we install on top of exsisting app, Let's wait for @shazron to advise so we don't waste time.
          Hide
          Yoh Suzuki added a comment -

          @emile - I observed that in order to kill my app from the task manager, it first hits my breakpoint in onResignActive (because you actually have to leave the app in order to see it in the task manager), and then my breakpoint in onAppTerminate (when I kill it in the task manager). The act of holding the power button to turn the phone off also triggers onResignActive.

          I figured this covers most scenarios, though there may be other situations (like losing power to the phone somehow, as you mentioned). If one of these other situations becomes a problem, I will definitely start making manual backup calls from JavaScript as you suggest. Thanks!

          (In that scenario, the trick will be to not call backup too often. If I'm going to setItem 20 different things, I'd like to call backup just once after they're all set, especially if localStorage contains lots of data. Maybe a quick solution would be a buffered call to Cordova.exec backup.)

          Show
          Yoh Suzuki added a comment - @emile - I observed that in order to kill my app from the task manager, it first hits my breakpoint in onResignActive (because you actually have to leave the app in order to see it in the task manager), and then my breakpoint in onAppTerminate (when I kill it in the task manager). The act of holding the power button to turn the phone off also triggers onResignActive. I figured this covers most scenarios, though there may be other situations (like losing power to the phone somehow, as you mentioned). If one of these other situations becomes a problem, I will definitely start making manual backup calls from JavaScript as you suggest. Thanks! (In that scenario, the trick will be to not call backup too often. If I'm going to setItem 20 different things, I'd like to call backup just once after they're all set, especially if localStorage contains lots of data. Maybe a quick solution would be a buffered call to Cordova.exec backup.)
          Hide
          Emile khattar added a comment -

          @Yoh turning of the phone didn't work for me all the times, inconsistent results in this case.(at least for me)
          Ok i agree you can implement your own backup logic i think it is case by case driven.

          It looks hard to fully mimic the localStorage setItem/getIten and unfortunately we can't re-compile webkit so we have to survive with these workaround untill we have a better persistent storage apis from cordova.

          Keep us posted with your observations

          gluck

          Show
          Emile khattar added a comment - @Yoh turning of the phone didn't work for me all the times, inconsistent results in this case.(at least for me) Ok i agree you can implement your own backup logic i think it is case by case driven. It looks hard to fully mimic the localStorage setItem/getIten and unfortunately we can't re-compile webkit so we have to survive with these workaround untill we have a better persistent storage apis from cordova. Keep us posted with your observations gluck
          Hide
          Yoh Suzuki added a comment - - edited

          This may be a silly question (I'm not an Objective-C programmer, nor am I familiar with native iOS development), but inside of verifyAndFixDatabaseLocations, if it requires a change to the plist (i.e. dirty), it writes out the plist file with the change to WebKitLocalStorageDatabasePathPreferenceKey.

          Will this change take effect immediately? If not (i.e. if it requires an app restart to take effect), then this could be why localStorage data is missing until the second launch after installing over top.

          Edit: OK, I see the [appPreferences synchronize], which I assume is supposed to make the change take effect immediately.

          Show
          Yoh Suzuki added a comment - - edited This may be a silly question (I'm not an Objective-C programmer, nor am I familiar with native iOS development), but inside of verifyAndFixDatabaseLocations, if it requires a change to the plist (i.e. dirty), it writes out the plist file with the change to WebKitLocalStorageDatabasePathPreferenceKey. Will this change take effect immediately? If not (i.e. if it requires an app restart to take effect), then this could be why localStorage data is missing until the second launch after installing over top. Edit: OK, I see the [appPreferences synchronize] , which I assume is supposed to make the change take effect immediately.
          Hide
          Shazron Abdullah added a comment -

          @Yoh - "on a new install and first run, it will try to restore a non-existent backup, this is normal." – this is because in a new app, there is nothing to restore. I've fixed it so it doesn't report anything, except on success (to be released soon).

          @Daniel - (programmatically modify the localstorage/websql location) - yes. You can do that by looking how in the code for verifyAndFixDatabaseLocations. I'm reluctant to support that because of the risk of side effects out of my control (who knows what things possibly WebKit or UIKit relies on... until its too late)

          @Emile - this upcoming version should streamline the backup/restore. I'm checking for file modification dates now, and it will only proceed if a backup or restore is newer.

          @Yoh - see CB-347, I suggested to someone to move code to applicationDidFinishLaunching instead of webViewDidStartLoad and that fixed the problem. I'll add this in the README

          Show
          Shazron Abdullah added a comment - @Yoh - "on a new install and first run, it will try to restore a non-existent backup, this is normal." – this is because in a new app, there is nothing to restore. I've fixed it so it doesn't report anything, except on success (to be released soon). @Daniel - (programmatically modify the localstorage/websql location) - yes. You can do that by looking how in the code for verifyAndFixDatabaseLocations. I'm reluctant to support that because of the risk of side effects out of my control (who knows what things possibly WebKit or UIKit relies on... until its too late) @Emile - this upcoming version should streamline the backup/restore. I'm checking for file modification dates now, and it will only proceed if a backup or restore is newer. @Yoh - see CB-347 , I suggested to someone to move code to applicationDidFinishLaunching instead of webViewDidStartLoad and that fixed the problem. I'll add this in the README
          Hide
          Shazron Abdullah added a comment -

          Update to CDVLocalStorage plugin:
          1. Backup/restore only on newer
          2. Update to README - put code in applicationDidFinishLaunching instead of webviewDidStartLoad

          Show
          Shazron Abdullah added a comment - Update to CDVLocalStorage plugin: 1. Backup/restore only on newer 2. Update to README - put code in applicationDidFinishLaunching instead of webviewDidStartLoad
          Hide
          Yoh Suzuki added a comment - - edited

          @Shazron - In Cordova 1.5.0, I do not see applicationDidFinishLaunching, and I do not see a UIWebView* inside of didFinishLaunchingWithOptions to pass to CDVLocalStorage initWithWebView.

          Show
          Yoh Suzuki added a comment - - edited @Shazron - In Cordova 1.5.0, I do not see applicationDidFinishLaunching, and I do not see a UIWebView* inside of didFinishLaunchingWithOptions to pass to CDVLocalStorage initWithWebView.
          Hide
          Shazron Abdullah added a comment -

          @Yoh it should be application:didFinishLaunchingWithOptions, correct - and yeah it's tricky because its designed to be a plugin that is resident (which is all handled properly in 1.6.0). All you need is for it to run it once to call verifyAndFixDatabaseLocations (for CB-347 fix) and also instantiate it in webviewDidStartLoad for CB-330 fix.

          I'll clean this up, but for now (to fix CB-347) in application:didFinishLaunchingWithOptions do:

          CDVLocalStorage* localStorage = [[CDVLocalStorage alloc] init];
          [localStorage verifyAndFixDatabaseLocations];
          [localStorage release];
          
          Show
          Shazron Abdullah added a comment - @Yoh it should be application:didFinishLaunchingWithOptions, correct - and yeah it's tricky because its designed to be a plugin that is resident (which is all handled properly in 1.6.0). All you need is for it to run it once to call verifyAndFixDatabaseLocations (for CB-347 fix) and also instantiate it in webviewDidStartLoad for CB-330 fix. I'll clean this up, but for now (to fix CB-347 ) in application:didFinishLaunchingWithOptions do: CDVLocalStorage* localStorage = [[CDVLocalStorage alloc] init]; [localStorage verifyAndFixDatabaseLocations]; [localStorage release];
          Hide
          Yoh Suzuki added a comment -

          @Shazron - That works!!! You are so awesome! Thank you so much!

          I think verifyAndFixDatabaseLocations in your snippet need some parameters?

           
          CDVLocalStorage* localStorage = [[CDVLocalStorage alloc] init];
          [localStorage verifyAndFixDatabaseLocations:nil withDict:nil];
          [localStorage release];
          

          Also, do you think we can take out the call to verifyAndFixDatabaseLocations inside of initWithWebView, since we're doing it in application:didFinishLaunchingWithOptions?

          Show
          Yoh Suzuki added a comment - @Shazron - That works!!! You are so awesome! Thank you so much! I think verifyAndFixDatabaseLocations in your snippet need some parameters? CDVLocalStorage* localStorage = [[CDVLocalStorage alloc] init]; [localStorage verifyAndFixDatabaseLocations:nil withDict:nil]; [localStorage release]; Also, do you think we can take out the call to verifyAndFixDatabaseLocations inside of initWithWebView, since we're doing it in application:didFinishLaunchingWithOptions?
          Hide
          Shazron Abdullah added a comment -

          @Yoh yup - was missing the params, sorry. Yes, it should only be called once, you can take out that call - but with the way the plugin is anyway, it will get called again (since every time you init the object, that gets called). All this will be cleaned up properly

          Show
          Shazron Abdullah added a comment - @Yoh yup - was missing the params, sorry. Yes, it should only be called once, you can take out that call - but with the way the plugin is anyway, it will get called again (since every time you init the object, that gets called). All this will be cleaned up properly
          Hide
          Shazron Abdullah added a comment -

          Updated plugin:
          1.Updated README, with an extra step to make it easier for users that want the CB-347 fix only
          2.Success/failure callbacks for the backup/restore JavaScript calls
          3. verifyAndFixDatabaseLocations takes into account whether the folder path is actually there (iOS 5.1 does not mean the dbs will always be in /Library/Cache - quite inconsistent)

          Show
          Shazron Abdullah added a comment - Updated plugin: 1.Updated README, with an extra step to make it easier for users that want the CB-347 fix only 2.Success/failure callbacks for the backup/restore JavaScript calls 3. verifyAndFixDatabaseLocations takes into account whether the folder path is actually there (iOS 5.1 does not mean the dbs will always be in /Library/Cache - quite inconsistent)
          Hide
          Siep de Vries added a comment -

          I tested the (previous) plugin and it seems to work nice, taking above comments in consideration. I however have a question. In the code, I see quite some calls like (IsiOSVersion(@"5.1")) ? @"Library/Caches" : @"Library/WebKit" to determine which path should be used. I must say, I'm not familiar with the call IsiOSVersion, but what happens if Apple plans to rollout iOS5.2 or iOS6.0? Will these checks then return the old paths instead of the new paths?

          Show
          Siep de Vries added a comment - I tested the (previous) plugin and it seems to work nice, taking above comments in consideration. I however have a question. In the code, I see quite some calls like (IsiOSVersion(@"5.1")) ? @"Library/Caches" : @"Library/WebKit" to determine which path should be used. I must say, I'm not familiar with the call IsiOSVersion, but what happens if Apple plans to rollout iOS5.2 or iOS6.0? Will these checks then return the old paths instead of the new paths?
          Hide
          Emile khattar added a comment - - edited

          @shazron: CDVCommandStatus_OK and CDVCommandStatus_ERROR and CDVPluginResult need to be defined for 1.4 and older

          if resolved it for 1.4.1 the same way you did for PGPLugin: https://github.com/emile818/PG_LocalStorage/

          Show
          Emile khattar added a comment - - edited @shazron: CDVCommandStatus_OK and CDVCommandStatus_ERROR and CDVPluginResult need to be defined for 1.4 and older if resolved it for 1.4.1 the same way you did for PGPLugin: https://github.com/emile818/PG_LocalStorage/
          Hide
          Shazron Abdullah added a comment -

          @Siep the naming of that macro is misleading - it really should be "IsAtLeastiOSVersion" - I'll change it.

          @Emile - thanks! this is what late night coding does to you, you forget to test for < 1.5 Will fix.

          Show
          Shazron Abdullah added a comment - @Siep the naming of that macro is misleading - it really should be "IsAtLeastiOSVersion" - I'll change it. @Emile - thanks! this is what late night coding does to you, you forget to test for < 1.5 Will fix.
          Hide
          Emile khattar added a comment -

          @shazron i didn't support 1.5 check the readme

          Show
          Emile khattar added a comment - @shazron i didn't support 1.5 check the readme
          Hide
          Shazron Abdullah added a comment -

          @Emile ha - I shouldn't have used the second person there, "you" in "you forget" === "me"

          Show
          Shazron Abdullah added a comment - @Emile ha - I shouldn't have used the second person there, "you" in "you forget" === "me"
          Hide
          Emile khattar added a comment -

          @shazron hahaha i thought you are talking to me because "late night coding" is common in here

          Thanks a lot for this fixing this issue, you are the savior of many of us i am pretty sure.

          Awaiting for your zip file

          cheers

          Show
          Emile khattar added a comment - @shazron hahaha i thought you are talking to me because "late night coding" is common in here Thanks a lot for this fixing this issue, you are the savior of many of us i am pretty sure. Awaiting for your zip file cheers
          Hide
          Shazron Abdullah added a comment -

          Updated plugin:
          1. Fixed 0.9.6-1.4.1 undefined symbol issues
          2. Renamed macro from IsiOSVersion to IsAtLeastiOSVersion

          Show
          Shazron Abdullah added a comment - Updated plugin: 1. Fixed 0.9.6-1.4.1 undefined symbol issues 2. Renamed macro from IsiOSVersion to IsAtLeastiOSVersion
          Hide
          Emile khattar added a comment -

          @shazron
          is this warning normal:
          "Incompatible pointer types assigning to 'CDVPluginResult *' from 'PluginResult *'"

          Also in the readme.txt: did you mean "didFinishLaunchingWithOptions" instead of "applicationDidFinishLaunching"
          and "initWithWebView:self.webView" instead of "initWithWebView:theWebView" ?

          Show
          Emile khattar added a comment - @shazron is this warning normal: "Incompatible pointer types assigning to 'CDVPluginResult *' from 'PluginResult *'" Also in the readme.txt: did you mean "didFinishLaunchingWithOptions" instead of "applicationDidFinishLaunching" and "initWithWebView:self.webView" instead of "initWithWebView:theWebView" ?
          Hide
          Shazron Abdullah added a comment -

          @Emile should be ok, don't worry about it. Huh. I wrote a totally new README.txt, that's not the one that's supposed to be in there. I'll track it down.

          Show
          Shazron Abdullah added a comment - @Emile should be ok, don't worry about it. Huh. I wrote a totally new README.txt, that's not the one that's supposed to be in there. I'll track it down.
          Hide
          Shazron Abdullah added a comment -

          Uploaded correct README that was missing from the plugin.

          Show
          Shazron Abdullah added a comment - Uploaded correct README that was missing from the plugin.
          Hide
          Davide Bertola added a comment - - edited

          Hi, I solved this issue in my app before coming across the jira bug. My strategy is simple.
          I move the default webkit databases (from both Caches/ for 5.0.1+ or Library/Webkit for older iOS)
          from their location to a safe location inside Documents folder.
          I do this only if the "source" database exists, and if "destination" in the safe location does not exists.
          Then I update the app preferences to pick up the databases from my Documents folder.
          This should be safe and simpler than backing up and restoring stuff around.

          This is the code I call from my application:didFinishLaunchingWithOptions:

              /* Fix problem with ios 5.0.1+ and Webkit databases described at the following urls:
               *   https://issues.apache.org/jira/browse/CB-347
               *   https://issues.apache.org/jira/browse/CB-330
               * My strategy is to move any existing database from default paths
               * to Documents/ and then changing app preferences accordingly
               */
              
              NSString* library = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)objectAtIndex:0];
              NSString* documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
              
              NSString *localStorageSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/LocalStorage";
              NSString *localStoragePath = [library stringByAppendingPathComponent:localStorageSubdir];
              NSString *localStorageDb = [localStoragePath stringByAppendingPathComponent:@"file__0.localstorage"];
              
              NSString *WebSQLSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/Databases";
              NSString *WebSQLPath = [library stringByAppendingPathComponent:WebSQLSubdir];
              NSString *WebSQLIndex = [WebSQLPath stringByAppendingPathComponent:@"Databases.db"];
              NSString *WebSQLDb = [WebSQLPath stringByAppendingPathComponent:@"file__0"];
              
              NSString *ourLocalStoragePath = [documents stringByAppendingPathComponent:@"LocalStorage"];;
              NSString *ourLocalStorageDb = [documents stringByAppendingPathComponent:@"file__0.localstorage"];
              
              NSString *ourWebSQLPath = [documents stringByAppendingPathComponent:@"Databases"];
              NSString *ourWebSQLIndex = [ourWebSQLPath stringByAppendingPathComponent:@"Databases.db"];
              NSString *ourWebSQLDb = [ourWebSQLPath stringByAppendingPathComponent:@"file__0"];
              
              NSFileManager* fileManager = [NSFileManager defaultManager];
              
              BOOL copy;
              NSError *err = nil; 
              copy = [fileManager fileExistsAtPath:localStorageDb] && ![fileManager fileExistsAtPath:ourLocalStorageDb];
              if (copy) {
                  [fileManager createDirectoryAtPath:ourLocalStoragePath withIntermediateDirectories:YES attributes:nil error:&err];
                  [fileManager copyItemAtPath:localStorageDb toPath:ourLocalStorageDb error:&err];
                  if (err == nil)
                      [fileManager removeItemAtPath:localStorageDb error:&err];
              }
              
              err = nil;
              copy = [fileManager fileExistsAtPath:WebSQLPath] && ![fileManager fileExistsAtPath:ourWebSQLPath];
              if (copy) {
                  [fileManager createDirectoryAtPath:ourWebSQLPath withIntermediateDirectories:YES attributes:nil error:&err];
                  [fileManager copyItemAtPath:WebSQLIndex toPath:ourWebSQLIndex error:&err];
                  [fileManager copyItemAtPath:WebSQLDb toPath:ourWebSQLDb error:&err];
                  if (err == nil)
                      [fileManager removeItemAtPath:WebSQLPath error:&err];
              }
              
              NSUserDefaults* appPreferences = [NSUserDefaults standardUserDefaults];
              NSBundle* mainBundle = [NSBundle mainBundle];
              
              NSString *bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent];
              NSString *bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@"CFBundleIdentifier"];
              NSString* libraryPreferences = @"Library/Preferences";
              
              NSString* appPlistPath = [[bundlePath stringByAppendingPathComponent:libraryPreferences]    stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", bundleIdentifier]];
              NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath];
              
              BOOL dirty = NO;
              
              NSString *value;
              NSString *key = @"WebKitLocalStorageDatabasePathPreferenceKey";
              value = [appPlistDict objectForKey: key];
              if (![value isEqual:ourLocalStoragePath]) {
                  [appPlistDict setValue:ourLocalStoragePath forKey:key];
                  dirty = YES;
              }
              
              key = @"WebDatabaseDirectory";
              value = [appPlistDict objectForKey: key];
              if (![value isEqual:ourWebSQLPath]) {
                  [appPlistDict setValue:ourWebSQLPath forKey:key];
                  dirty = YES;
              }
              
              if (dirty) 
              {
                  BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES];
                  NSLog(@"Fix applied for database locations?: %@", ok? @"YES":@"NO");
                  [appPreferences synchronize];
              }
          

          What do you think ?

          Also, I have a suggestion for this plugin.
          It is possible to remove the data storage quota limit for WebkitSQL by running simple sqlite queries on the sql files. I am currently doing this with my plugin https://github.com/davibe/Phonegap-SQLitePlugin using it from javascript code to open Databases.db and run the following queries:

          update origins set quota = '999999999999' where origin = 'file__0';
          update databases set estimatedSize = '999999999999' where name = '" + dbName + "';
          Where db name is the name of the db being patched.
          

          About the mentioned Phonegap SQLitePlugin.
          I tried to use my sqlite plugin instead of the database interface offered by webkit. I have read Edgar Canas suggesting this. I can tell from my experience that for some reason It's much slower. The bottleneck seems to be passing long queries (I store jsons that are over 1Mb) from the webview to native code. WebkitSQLite does not suffer from this.
          By the way I have plans porting it to Cordova, any suggestions are welcome.

          Show
          Davide Bertola added a comment - - edited Hi, I solved this issue in my app before coming across the jira bug. My strategy is simple. I move the default webkit databases (from both Caches/ for 5.0.1+ or Library/Webkit for older iOS) from their location to a safe location inside Documents folder. I do this only if the "source" database exists, and if "destination" in the safe location does not exists. Then I update the app preferences to pick up the databases from my Documents folder. This should be safe and simpler than backing up and restoring stuff around. This is the code I call from my application:didFinishLaunchingWithOptions: /* Fix problem with ios 5.0.1+ and Webkit databases described at the following urls: * https: //issues.apache.org/jira/browse/CB-347 * https: //issues.apache.org/jira/browse/CB-330 * My strategy is to move any existing database from default paths * to Documents/ and then changing app preferences accordingly */ NSString* library = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)objectAtIndex:0]; NSString* documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *localStorageSubdir = (IsAtLeastiOSVersion(@ "5.1" )) ? @ "Caches" : @ "WebKit/LocalStorage" ; NSString *localStoragePath = [library stringByAppendingPathComponent:localStorageSubdir]; NSString *localStorageDb = [localStoragePath stringByAppendingPathComponent:@ "file__0.localstorage" ]; NSString *WebSQLSubdir = (IsAtLeastiOSVersion(@ "5.1" )) ? @ "Caches" : @ "WebKit/Databases" ; NSString *WebSQLPath = [library stringByAppendingPathComponent:WebSQLSubdir]; NSString *WebSQLIndex = [WebSQLPath stringByAppendingPathComponent:@ "Databases.db" ]; NSString *WebSQLDb = [WebSQLPath stringByAppendingPathComponent:@ "file__0" ]; NSString *ourLocalStoragePath = [documents stringByAppendingPathComponent:@ "LocalStorage" ];; NSString *ourLocalStorageDb = [documents stringByAppendingPathComponent:@ "file__0.localstorage" ]; NSString *ourWebSQLPath = [documents stringByAppendingPathComponent:@ "Databases" ]; NSString *ourWebSQLIndex = [ourWebSQLPath stringByAppendingPathComponent:@ "Databases.db" ]; NSString *ourWebSQLDb = [ourWebSQLPath stringByAppendingPathComponent:@ "file__0" ]; NSFileManager* fileManager = [NSFileManager defaultManager]; BOOL copy; NSError *err = nil; copy = [fileManager fileExistsAtPath:localStorageDb] && ![fileManager fileExistsAtPath:ourLocalStorageDb]; if (copy) { [fileManager createDirectoryAtPath:ourLocalStoragePath withIntermediateDirectories:YES attributes:nil error:&err]; [fileManager copyItemAtPath:localStorageDb toPath:ourLocalStorageDb error:&err]; if (err == nil) [fileManager removeItemAtPath:localStorageDb error:&err]; } err = nil; copy = [fileManager fileExistsAtPath:WebSQLPath] && ![fileManager fileExistsAtPath:ourWebSQLPath]; if (copy) { [fileManager createDirectoryAtPath:ourWebSQLPath withIntermediateDirectories:YES attributes:nil error:&err]; [fileManager copyItemAtPath:WebSQLIndex toPath:ourWebSQLIndex error:&err]; [fileManager copyItemAtPath:WebSQLDb toPath:ourWebSQLDb error:&err]; if (err == nil) [fileManager removeItemAtPath:WebSQLPath error:&err]; } NSUserDefaults* appPreferences = [NSUserDefaults standardUserDefaults]; NSBundle* mainBundle = [NSBundle mainBundle]; NSString *bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent]; NSString *bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@ "CFBundleIdentifier" ]; NSString* libraryPreferences = @ "Library/Preferences" ; NSString* appPlistPath = [[bundlePath stringByAppendingPathComponent:libraryPreferences] stringByAppendingPathComponent:[NSString stringWithFormat:@ "%@.plist" , bundleIdentifier]]; NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath]; BOOL dirty = NO; NSString *value; NSString *key = @ "WebKitLocalStorageDatabasePathPreferenceKey" ; value = [appPlistDict objectForKey: key]; if (![value isEqual:ourLocalStoragePath]) { [appPlistDict setValue:ourLocalStoragePath forKey:key]; dirty = YES; } key = @ "WebDatabaseDirectory" ; value = [appPlistDict objectForKey: key]; if (![value isEqual:ourWebSQLPath]) { [appPlistDict setValue:ourWebSQLPath forKey:key]; dirty = YES; } if (dirty) { BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES]; NSLog(@ "Fix applied for database locations?: %@" , ok? @ "YES" :@ "NO" ); [appPreferences synchronize]; } What do you think ? Also, I have a suggestion for this plugin. It is possible to remove the data storage quota limit for WebkitSQL by running simple sqlite queries on the sql files. I am currently doing this with my plugin https://github.com/davibe/Phonegap-SQLitePlugin using it from javascript code to open Databases.db and run the following queries: update origins set quota = '999999999999' where origin = 'file__0'; update databases set estimatedSize = '999999999999' where name = ' " + dbName + " '; Where db name is the name of the db being patched. About the mentioned Phonegap SQLitePlugin. I tried to use my sqlite plugin instead of the database interface offered by webkit. I have read Edgar Canas suggesting this. I can tell from my experience that for some reason It's much slower. The bottleneck seems to be passing long queries (I store jsons that are over 1Mb) from the webview to native code. WebkitSQLite does not suffer from this. By the way I have plans porting it to Cordova, any suggestions are welcome.
          Hide
          Shazron Abdullah added a comment -

          Re: "Then I update the app preferences to pick up the databases from my Documents folder.
          This should be safe and simpler than backing up and restoring stuff around."

          I considered this but ultimately rejected it because of the possibility of side-effects. I mentioned this earlier here: https://issues.apache.org/jira/browse/CB-330?focusedCommentId=13236224&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13236224

          I realize that CB-347 I am already modifying it - but that's only to "patch" their bug, not to re-direct the storage location which Apple may/may not frown upon.

          Show
          Shazron Abdullah added a comment - Re: "Then I update the app preferences to pick up the databases from my Documents folder. This should be safe and simpler than backing up and restoring stuff around." I considered this but ultimately rejected it because of the possibility of side-effects. I mentioned this earlier here: https://issues.apache.org/jira/browse/CB-330?focusedCommentId=13236224&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13236224 I realize that CB-347 I am already modifying it - but that's only to "patch" their bug, not to re-direct the storage location which Apple may/may not frown upon.
          Hide
          Daniel added a comment -

          Hi Davide!

          Thanks for posting your code here! Although I understand why Shazron decided to go and implement a more 'Apple compliant fix', I like the idea of changing the localstorage location itself much more. It feels more robust compared to going back and forth using backup-data.

          First I put your code in the

          webViewDidFinishLoad

          method. However that was not working for me after restarting the program. Then I used your code in the

          didFinishLaunchingWithOptions

          method which worked perfectly.

          I did modify one line of your code, because otherwise it creates 2 localstorage files in the Application/Documents folder:

            // your code
            NSString *ourLocalStorageDb = [documents stringByAppendingPathComponent:@"file__0.localstorage"];
          
            // changed to
            NSString *ourLocalStorageDb = [ourLocalStoragePath stringByAppendingPathComponent:@"file__0.localstorage"];
          
          Show
          Daniel added a comment - Hi Davide! Thanks for posting your code here! Although I understand why Shazron decided to go and implement a more 'Apple compliant fix', I like the idea of changing the localstorage location itself much more. It feels more robust compared to going back and forth using backup-data. First I put your code in the webViewDidFinishLoad method. However that was not working for me after restarting the program. Then I used your code in the didFinishLaunchingWithOptions method which worked perfectly. I did modify one line of your code, because otherwise it creates 2 localstorage files in the Application/Documents folder: // your code NSString *ourLocalStorageDb = [documents stringByAppendingPathComponent:@ "file__0.localstorage" ]; // changed to NSString *ourLocalStorageDb = [ourLocalStoragePath stringByAppendingPathComponent:@ "file__0.localstorage" ];
          Hide
          Paul DeFalco added a comment -

          I was having trouble with trying to add a column to a table and found this thread with help from phonegap support. I know very little about Objective C and just use xCode to build my phonegap - Sencha Touch app.

          When I try to implement the plugin in xCode I'm getting warnings similar to "Incompatible Objective-C types assigning 'struct PGPlugin ', expected 'struct CDVLocalStorage '".

          The fix seems to be working but I don't like seeing all of those warnings.
          Can anyone help?

          Show
          Paul DeFalco added a comment - I was having trouble with trying to add a column to a table and found this thread with help from phonegap support. I know very little about Objective C and just use xCode to build my phonegap - Sencha Touch app. When I try to implement the plugin in xCode I'm getting warnings similar to "Incompatible Objective-C types assigning 'struct PGPlugin ', expected 'struct CDVLocalStorage '". The fix seems to be working but I don't like seeing all of those warnings. Can anyone help?
          Hide
          Richard Kimber added a comment -

          Hi @Sharon,

          I'm wondering should:

          return [ super webViewDidStartLoad:theWebView ];

          actually be:

          return [self.viewController webViewDidStartLoad:theWebView];

          I get an error with the first version of the code, on PG 1.4.1.

          Rich

          Show
          Richard Kimber added a comment - Hi @Sharon, I'm wondering should: return [ super webViewDidStartLoad:theWebView ]; actually be: return [self.viewController webViewDidStartLoad:theWebView] ; I get an error with the first version of the code, on PG 1.4.1. Rich
          Hide
          Shazron Abdullah added a comment -

          @Paul those warnings should be harmless (in your version's case with the compat. headers CDVLocalStorage is a CDVPlugin is a PGPlugin) - unfortunately to make it work on all versions I have to leave this warning in, if not it gets more complex with compile conditionals, and more instructions.

          @Richard you are correct: https://github.com/apache/incubator-cordova-ios/blob/1.4.1/PhoneGap-based%20Application/Classes/AppDelegate.m#L173 (or change super to self, that should work I think as well). Sorry - a bit challenging testing for all versions!

          Show
          Shazron Abdullah added a comment - @Paul those warnings should be harmless (in your version's case with the compat. headers CDVLocalStorage is a CDVPlugin is a PGPlugin) - unfortunately to make it work on all versions I have to leave this warning in, if not it gets more complex with compile conditionals, and more instructions. @Richard you are correct: https://github.com/apache/incubator-cordova-ios/blob/1.4.1/PhoneGap-based%20Application/Classes/AppDelegate.m#L173 (or change super to self, that should work I think as well). Sorry - a bit challenging testing for all versions!
          Hide
          Richard Kimber added a comment -

          I'm very appreciative for the work you've done @Shazron. I only wish I had the time to be more involved.

          Rich

          Show
          Richard Kimber added a comment - I'm very appreciative for the work you've done @Shazron. I only wish I had the time to be more involved. Rich
          Hide
          Sean added a comment -

          @Davide I really like your idea of just changing the location of where data is saved. I added your code as the block that runs when didFinishLaunchingWithOptions runs but I get a compile error I think you might understand. I've never worked with this language so fixing it is not obvious to me.

          NSString *localStorageSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/LocalStorage";

          The error I get is:

          Undefined symbols for architecture armv6:
          "_IsAtLeastiOSVersion", referenced from:
          -[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
          ld: symbol(s) not found for architecture armv6
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

          Any help you, or anyone, can send my way is greatly appreciated.

          Show
          Sean added a comment - @Davide I really like your idea of just changing the location of where data is saved. I added your code as the block that runs when didFinishLaunchingWithOptions runs but I get a compile error I think you might understand. I've never worked with this language so fixing it is not obvious to me. NSString *localStorageSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/LocalStorage"; The error I get is: Undefined symbols for architecture armv6: "_IsAtLeastiOSVersion", referenced from: - [AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o ld: symbol(s) not found for architecture armv6 clang: error: linker command failed with exit code 1 (use -v to see invocation) Any help you, or anyone, can send my way is greatly appreciated.
          Hide
          Daniel added a comment -

          Hi Sean,

          I faced the same issue. You need to place the following code fragment in AppDelegate.h file:

          /* 
           * Returns YES if it is at least version specified as NSString(X)
           */
          #define IsAtLeastiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch] !=      NSOrderedAscending)
          
          Show
          Daniel added a comment - Hi Sean, I faced the same issue. You need to place the following code fragment in AppDelegate.h file: /* * Returns YES if it is at least version specified as NSString(X) */ #define IsAtLeastiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch] != NSOrderedAscending)
          Hide
          Sean added a comment -

          @Daniel thank you very much. That worked for me. Unfortunately, the data in local storage did not persist after I killed the running app on my iPad and restarted it. Did you experience this?

          Thanks in advance.

          Show
          Sean added a comment - @Daniel thank you very much. That worked for me. Unfortunately, the data in local storage did not persist after I killed the running app on my iPad and restarted it. Did you experience this? Thanks in advance.
          Hide
          Daniel added a comment -

          For me it was working. I made one minor change to Davide's code, which I explained in my previous comment: https://issues.apache.org/jira/browse/CB-330?focusedCommentId=13238225&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13238225

          Show
          Daniel added a comment - For me it was working. I made one minor change to Davide's code, which I explained in my previous comment: https://issues.apache.org/jira/browse/CB-330?focusedCommentId=13238225&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13238225
          Hide
          Sean added a comment -

          @Daniel and @Davide, thanks for your very helpful posts. My app is now working as expected

          Show
          Sean added a comment - @Daniel and @Davide, thanks for your very helpful posts. My app is now working as expected
          Hide
          Kara added a comment -

          thanks thanks thanks @Daniel & @Davide !! You are my heroes

          @Sean just give it another try, that's what I first thought when I killed the app... it didn't work I don't know why, but if you access the app again it will be working like expected.

          Show
          Kara added a comment - thanks thanks thanks @Daniel & @Davide !! You are my heroes @Sean just give it another try, that's what I first thought when I killed the app... it didn't work I don't know why, but if you access the app again it will be working like expected.
          Hide
          Chris Emerson added a comment -

          Just wanted to say THANK YOU to Shazron Abdullah and everyone else who has contributed here!

          Show
          Chris Emerson added a comment - Just wanted to say THANK YOU to Shazron Abdullah and everyone else who has contributed here!
          Hide
          Andy Andrei Hurjui added a comment -

          Hello,
          I've read the entire thread, and installed Cordova-1.6.0 but i still have the issue reproducing itself.
          Is there anything to do to Cordova 1.6.0 besides installing it in order to fix the issue ?
          Is there some code or files i should search for to be sure I've installed correctly ?

          Thanks,
          Andy

          Show
          Andy Andrei Hurjui added a comment - Hello, I've read the entire thread, and installed Cordova-1.6.0 but i still have the issue reproducing itself. Is there anything to do to Cordova 1.6.0 besides installing it in order to fix the issue ? Is there some code or files i should search for to be sure I've installed correctly ? Thanks, Andy
          Hide
          Samuel Michelot added a comment - - edited

          I think I have found a bug. The verifyAndFixDatabaseLocations is called on the first install, even if it's on iOS4.3.
          The consequences are that the LocalStorage files are stored in the Caches folder, even if we run in iOS version before 5.1 (tested in the simulator in 4.3).

          Is it normal?

          Show
          Samuel Michelot added a comment - - edited I think I have found a bug. The verifyAndFixDatabaseLocations is called on the first install, even if it's on iOS4.3. The consequences are that the LocalStorage files are stored in the Caches folder, even if we run in iOS version before 5.1 (tested in the simulator in 4.3). Is it normal?
          Hide
          Shazron Abdullah added a comment -

          @Samuel It will be called, but the fix will not be applied. It checks whether the bug occurs in the .plist, and will not fix it if the setting is correct. See: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L269

          Show
          Shazron Abdullah added a comment - @Samuel It will be called, but the fix will not be applied. It checks whether the bug occurs in the .plist, and will not fix it if the setting is correct. See: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L269
          Hide
          Samuel Michelot added a comment -

          Thanks for your quick answer Shazron. But after new testing, I can confirm that there is a problem (at least in the iOS 4.3 simulator). To reproduce the problem, I need to delete the app, then reinstall it, and launch it twice in the iOS 4.3 simulator.

          I added this log in the verifyAndFixDatabaseLocations :
          NSLog(@"Error in database locations?: Old Value=%@, newValue=%@", value, newBundlePath);

          And I got this on the second launch (on the first launch, the fix is not applied) :

          Error in database locations?: Old Value=(null), newValue=/Users/sam/Library/Application Support/iPhone Simulator/4.3.2/Applications/E8484BD2-0BDF-4058-8121-CF14483F8440/Library/Caches
          2012-04-17 15:52:30.896 Mosa_fr_es[10279:12e03] Fix applied for database locations?: YES

          And you can see in the following screenshot that 2 DB are created (in WebKit for the first launch, and in Caches for the second launch) :
          http://cl.ly/3x0P0x3I3z0w040Z2K0Y

          Maybe we shouldn't apply the fix if the value is null, or only call this method when iOS >=5.1 ?

          Show
          Samuel Michelot added a comment - Thanks for your quick answer Shazron. But after new testing, I can confirm that there is a problem (at least in the iOS 4.3 simulator). To reproduce the problem, I need to delete the app, then reinstall it, and launch it twice in the iOS 4.3 simulator. I added this log in the verifyAndFixDatabaseLocations : NSLog(@"Error in database locations?: Old Value=%@, newValue=%@", value, newBundlePath); And I got this on the second launch (on the first launch, the fix is not applied) : Error in database locations?: Old Value=(null), newValue=/Users/sam/Library/Application Support/iPhone Simulator/4.3.2/Applications/E8484BD2-0BDF-4058-8121-CF14483F8440/Library/Caches 2012-04-17 15:52:30.896 Mosa_fr_es [10279:12e03] Fix applied for database locations?: YES And you can see in the following screenshot that 2 DB are created (in WebKit for the first launch, and in Caches for the second launch) : http://cl.ly/3x0P0x3I3z0w040Z2K0Y Maybe we shouldn't apply the fix if the value is null, or only call this method when iOS >=5.1 ?
          Hide
          Shazron Abdullah added a comment -

          @Samuel you are correct. I will add the nil check here as well: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L269 This fix should take care of the library/caches dupe database issue as well. I've examined the flow and if it has the problem in the .plist, this code block should take care of it based on the folder existing: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L273-276 and the folder can only exist if the key exists (which we will check for now).

          Show
          Shazron Abdullah added a comment - @Samuel you are correct. I will add the nil check here as well: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L269 This fix should take care of the library/caches dupe database issue as well. I've examined the flow and if it has the problem in the .plist, this code block should take care of it based on the folder existing: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L273-276 and the folder can only exist if the key exists (which we will check for now).
          Show
          Shazron Abdullah added a comment - Fix updated in 1.6.1 - http://git-wip-us.apache.org/repos/asf?p=incubator-cordova-ios.git;a=commit;h=d358ab2b
          Hide
          Samuel Michelot added a comment -

          Thanks a lot for your excellent work Shazron!

          Show
          Samuel Michelot added a comment - Thanks a lot for your excellent work Shazron!
          Hide
          Wytze added a comment -

          Hi Shazron, I get two errors after setting up the CDVPlugin.

          The error occurs while compiling AppDelegate.m and again while compiling CDVLocalStorage.h

          In both cases, XCode says:

          Cordova/CDVPlugin.h file not found.

          I'm not sure what to do about this, since I am not an Objective-C programmer. Something that puzzles me in particular is that the content of the file CDVPlugin.h is nothing more than a bunch of comments and the command #import <Cordova/CDVPlugin.h>. To me it doesn't make sense that a file would try to import itself...

          Show
          Wytze added a comment - Hi Shazron, I get two errors after setting up the CDVPlugin. The error occurs while compiling AppDelegate.m and again while compiling CDVLocalStorage.h In both cases, XCode says: Cordova/CDVPlugin.h file not found. I'm not sure what to do about this, since I am not an Objective-C programmer. Something that puzzles me in particular is that the content of the file CDVPlugin.h is nothing more than a bunch of comments and the command #import <Cordova/CDVPlugin.h>. To me it doesn't make sense that a file would try to import itself...
          Hide
          Shazron Abdullah added a comment -

          @Wytze what version are you targeting? There's different instructions for different versions in the README

          Show
          Shazron Abdullah added a comment - @Wytze what version are you targeting? There's different instructions for different versions in the README
          Show
          Shazron Abdullah added a comment - Blog post summarizing this issue: http://phonegap.com/2012/04/18/ios-5-1-and-the-embedded-uiwebview-with-cordova/
          Hide
          Wytze added a comment -

          @Shazron, I am using Cordova 1.5.0 and following the instructions for that version.

          I am using Xcode 3.2.6 on a Snow Leopard running OSX 10.6.8.

          Show
          Wytze added a comment - @Shazron, I am using Cordova 1.5.0 and following the instructions for that version. I am using Xcode 3.2.6 on a Snow Leopard running OSX 10.6.8.
          Hide
          Wytze added a comment -

          @Shazron PS: My first wild guess is that something is not right with the process of adding the files. I add them by doubleclicking on the Plugins folder and choosing Add existing files.

          • I then select the files and get a popup asking me how to add them.
          • I check the box that says 'Copy items into destination folder (if necessary)'
          • I leave the radiobox choice about folders on 'Recursively create groups for any added folders'
          • And I press 'Add'
          Show
          Wytze added a comment - @Shazron PS: My first wild guess is that something is not right with the process of adding the files. I add them by doubleclicking on the Plugins folder and choosing Add existing files. I then select the files and get a popup asking me how to add them. I check the box that says 'Copy items into destination folder (if necessary)' I leave the radiobox choice about folders on 'Recursively create groups for any added folders' And I press 'Add'
          Hide
          Wytze added a comment -

          @Shazron, after retrying for a third time I seem to have gotten something right, or done something else wrong. The old error messages have gone. I now get only one error regarding "isAtLeastiOSVersion".

          I've seen the solution provided by @Sean to include a snippet defining isAtLeastiOSVersion in appDelegate.h. But that has not made a difference.

          I seem to be so close yet so far from launching my app.

          Undefined symbols:
          "_IsAtLeastiOSVersion", referenced from:
          -[CDVLocalStorage initWithWebView:] in CDVLocalStorage.o
          -[CDVLocalStorage initWithWebView:] in CDVLocalStorage.o
          -[CDVLocalStorage initWithWebView:] in CDVLocalStorage.o
          ld: symbol(s) not found
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

          Show
          Wytze added a comment - @Shazron, after retrying for a third time I seem to have gotten something right, or done something else wrong. The old error messages have gone. I now get only one error regarding "isAtLeastiOSVersion". I've seen the solution provided by @Sean to include a snippet defining isAtLeastiOSVersion in appDelegate.h. But that has not made a difference. I seem to be so close yet so far from launching my app. Undefined symbols: "_IsAtLeastiOSVersion", referenced from: - [CDVLocalStorage initWithWebView:] in CDVLocalStorage.o - [CDVLocalStorage initWithWebView:] in CDVLocalStorage.o - [CDVLocalStorage initWithWebView:] in CDVLocalStorage.o ld: symbol(s) not found clang: error: linker command failed with exit code 1 (use -v to see invocation)
          Hide
          Wytze added a comment -

          Sorry to be so spammy. I noticed in the blog that you referenced that version 1.6.1 is out and fixes all these problems. So I am ignoring the problem above.
          1.6.1 brings new issues, but I'll complain about those elsewhere.

          Show
          Wytze added a comment - Sorry to be so spammy. I noticed in the blog that you referenced that version 1.6.1 is out and fixes all these problems. So I am ignoring the problem above. 1.6.1 brings new issues, but I'll complain about those elsewhere.
          Hide
          Shazron Abdullah added a comment -

          Added a diagnostics plugin to troubleshoot issues. Please install and run (see README.txt) and check your console log.

          Show
          Shazron Abdullah added a comment - Added a diagnostics plugin to troubleshoot issues. Please install and run (see README.txt) and check your console log.
          Hide
          Angelo Marras added a comment -

          I thought the issue was fixed by just upgrading to Phonegap 1.6.1. It worked only after doing steps 4 to 6 described in the CDVLocalStoragePlugin-Readme.

          This workaround should be documented somewhere (Wiki or Readme), because it's a crucial issue for every iOS App using WebSQL/Localstorage.

          Show
          Angelo Marras added a comment - I thought the issue was fixed by just upgrading to Phonegap 1.6.1. It worked only after doing steps 4 to 6 described in the CDVLocalStoragePlugin-Readme. This workaround should be documented somewhere (Wiki or Readme), because it's a crucial issue for every iOS App using WebSQL/Localstorage.
          Hide
          Shazron Abdullah added a comment -

          The steps 4 to 6 are incorporated in 1.6.1:

          initialized at startup: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVViewController.m#L167

          which calls this init function to apply the fix:
          https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L107

          which fixes it here:
          https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L243

          also step 6 is here:
          https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L309

          This all happens before the UIWebView is loaded. Run the diagnostic plugin and report back - like I said, it might be an edge case in YOUR setup, I won't know until I see that report.

          Show
          Shazron Abdullah added a comment - The steps 4 to 6 are incorporated in 1.6.1: initialized at startup: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVViewController.m#L167 which calls this init function to apply the fix: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L107 which fixes it here: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L243 also step 6 is here: https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m#L309 This all happens before the UIWebView is loaded. Run the diagnostic plugin and report back - like I said, it might be an edge case in YOUR setup, I won't know until I see that report.
          Hide
          Angelo Marras added a comment -

          After the first install:

          ===Start CDVLocalStorageDiagnostics==========
          iOS version: 5.1
          =============================================
          Printing list of backup info.
          --------------------------------------
          Label: localStorage database
          shouldBackup: NO shouldRestore: NO
          Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/file__0.localstorage Exists?: NO
          Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/localstorage.appdata.db Exists?: NO
          --------------------------------------
          Label: websql main database
          shouldBackup: YES shouldRestore: NO
          Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/Databases.db Exists?: YES
          Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/websqlmain.appdata.db Exists?: NO
          --------------------------------------
          Label: websql databases
          shouldBackup: YES shouldRestore: NO
          Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/file__0 Exists?: YES
          Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/websqldbs.appdata.db Exists?: NO
          =============================================
          Printing folder locations, check for existence.
          Path /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches exists?: YES
          Path /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/WebKit exists?: NO
          =============================================
          Checking plist /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Preferences/ch.baz.epaper.plist for WebKit keys.
          Key: WebKitLocalStorageDatabasePathPreferenceKey Value: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches
          Key: WebDatabaseDirectory Value: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches
          ===End CDVLocalStorageDiagnostics============

          After app update:

          ===Start CDVLocalStorageDiagnostics==========
          iOS version: 5.1
          =============================================
          Printing list of backup info.
          --------------------------------------
          Label: localStorage database
          shouldBackup: NO shouldRestore: NO
          Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/file__0.localstorage Exists?: YES
          Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/localstorage.appdata.db Exists?: YES
          --------------------------------------
          Label: websql main database
          shouldBackup: NO shouldRestore: NO
          Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/Databases.db Exists?: YES
          Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/websqlmain.appdata.db Exists?: YES
          --------------------------------------
          Label: websql databases
          shouldBackup: NO shouldRestore: NO
          Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/file__0 Exists?: YES
          Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/websqldbs.appdata.db Exists?: YES
          =============================================
          Printing folder locations, check for existence.
          Path /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches exists?: YES
          Path /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/WebKit exists?: NO
          =============================================
          Checking plist /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Preferences/ch.baz.epaper.plist for WebKit keys.
          Key: WebKitLocalStorageDatabasePathPreferenceKey Value: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches
          Key: WebDatabaseDirectory Value: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches
          ===End CDVLocalStorageDiagnostics============

          And the error message: deny file-write-create /private/var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694

          Show
          Angelo Marras added a comment - After the first install: ===Start CDVLocalStorageDiagnostics========== iOS version: 5.1 ============================================= Printing list of backup info. -------------------------------------- Label: localStorage database shouldBackup: NO shouldRestore: NO Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/file__0.localstorage Exists?: NO Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/localstorage.appdata.db Exists?: NO -------------------------------------- Label: websql main database shouldBackup: YES shouldRestore: NO Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/Databases.db Exists?: YES Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/websqlmain.appdata.db Exists?: NO -------------------------------------- Label: websql databases shouldBackup: YES shouldRestore: NO Original: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches/file__0 Exists?: YES Backup: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Documents/Backups/websqldbs.appdata.db Exists?: NO ============================================= Printing folder locations, check for existence. Path /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches exists?: YES Path /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/WebKit exists?: NO ============================================= Checking plist /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Preferences/ch.baz.epaper.plist for WebKit keys. Key: WebKitLocalStorageDatabasePathPreferenceKey Value: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches Key: WebDatabaseDirectory Value: /var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694/Library/Caches ===End CDVLocalStorageDiagnostics============ After app update: ===Start CDVLocalStorageDiagnostics========== iOS version: 5.1 ============================================= Printing list of backup info. -------------------------------------- Label: localStorage database shouldBackup: NO shouldRestore: NO Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/file__0.localstorage Exists?: YES Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/localstorage.appdata.db Exists?: YES -------------------------------------- Label: websql main database shouldBackup: NO shouldRestore: NO Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/Databases.db Exists?: YES Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/websqlmain.appdata.db Exists?: YES -------------------------------------- Label: websql databases shouldBackup: NO shouldRestore: NO Original: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches/file__0 Exists?: YES Backup: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Documents/Backups/websqldbs.appdata.db Exists?: YES ============================================= Printing folder locations, check for existence. Path /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches exists?: YES Path /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/WebKit exists?: NO ============================================= Checking plist /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Preferences/ch.baz.epaper.plist for WebKit keys. Key: WebKitLocalStorageDatabasePathPreferenceKey Value: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches Key: WebDatabaseDirectory Value: /var/mobile/Applications/D08A19B0-0AC0-4C3D-9645-A5992271AB33/Library/Caches ===End CDVLocalStorageDiagnostics============ And the error message: deny file-write-create /private/var/mobile/Applications/3EC7A50D-4148-449A-A5A5-FDB297820694
          Hide
          Shazron Abdullah added a comment -

          @Angelo thanks for the report, it really helps.

          This appears to be the same problem I commented on here: https://issues.apache.org/jira/browse/CB-347?focusedCommentId=13261034&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13261034

          Can we continue there since this is really a CB-347 fix issue.

          Show
          Shazron Abdullah added a comment - @Angelo thanks for the report, it really helps. This appears to be the same problem I commented on here: https://issues.apache.org/jira/browse/CB-347?focusedCommentId=13261034&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13261034 Can we continue there since this is really a CB-347 fix issue.
          Hide
          Zach Smith added a comment -

          Ok I have applied this to 1.4.1. The app builds, seems to work fine, but when the home button is hit (in the simulator) I get "EXC_BAD_ACCESS" on line:

          [[UIApplication sharedApplication] endBackgroundTask: backgroundTaskID];

          from onResignActive in CDVLocalStorage.m

          Any ideas?

          Show
          Zach Smith added a comment - Ok I have applied this to 1.4.1. The app builds, seems to work fine, but when the home button is hit (in the simulator) I get "EXC_BAD_ACCESS" on line: [ [UIApplication sharedApplication] endBackgroundTask: backgroundTaskID]; from onResignActive in CDVLocalStorage.m Any ideas?
          Hide
          Shazron Abdullah added a comment -

          Which code exactly did you grab for the plugin when you said you "applied this to 1.4.1"?

          Show
          Shazron Abdullah added a comment - Which code exactly did you grab for the plugin when you said you "applied this to 1.4.1"?
          Hide
          Zach Smith added a comment -

          I downloaded the CDVLocalStoragePlugin.zip and applied it the way the README describes.

          Show
          Zach Smith added a comment - I downloaded the CDVLocalStoragePlugin.zip and applied it the way the README describes.
          Hide
          Zach Smith added a comment -

          Any ideas? I did everything the README says, if I comment out the lines:

          //[[UIApplication sharedApplication] endBackgroundTask: backgroundTaskID];
          //backgroundTaskID = UIBackgroundTaskInvalid;

          it works, but that honestly doesn't seem like a great idea.

          Show
          Zach Smith added a comment - Any ideas? I did everything the README says, if I comment out the lines: //[ [UIApplication sharedApplication] endBackgroundTask: backgroundTaskID]; //backgroundTaskID = UIBackgroundTaskInvalid; it works, but that honestly doesn't seem like a great idea.
          Show
          Shazron Abdullah added a comment - @Zach can you try using the latest: 1. https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.m 2. https://github.com/apache/incubator-cordova-ios/blob/master/CordovaLib/Classes/CDVLocalStorage.h
          Hide
          Dewang Shah added a comment -

          This issue seems to have returned after iOS 6. Looking at the code in CDVLocalStorage, there is a check for the version to be < 6.0

          NSString* original = [[appLibraryFolder stringByAppendingPathComponent :
          (IsAtLeastiOSVersion(@"5.1") && !IsAtLeastiOSVersion(@"6.0")) ? @"Caches":@"WebKit/LocalStorage"]
          stringByAppendingPathComponent:@"file__0.localstorage"];

          As a result data for a new app on iOS 6 is now lost when the app is closed and then restarted. Strangely enough the data is only lost on the first run. From the second run onwards data is persisted.

          Show
          Dewang Shah added a comment - This issue seems to have returned after iOS 6. Looking at the code in CDVLocalStorage, there is a check for the version to be < 6.0 NSString* original = [[appLibraryFolder stringByAppendingPathComponent : (IsAtLeastiOSVersion(@"5.1") && !IsAtLeastiOSVersion(@"6.0")) ? @"Caches":@"WebKit/LocalStorage"] stringByAppendingPathComponent:@"file__0.localstorage"]; As a result data for a new app on iOS 6 is now lost when the app is closed and then restarted. Strangely enough the data is only lost on the first run. From the second run onwards data is persisted.
          Hide
          Christian Kuetbach added a comment -

          I can confirm this bug with iOS 6. Wen run into this problem and filed a bugreport:

          https://issues.apache.org/jira/browse/CB-1535

          Show
          Christian Kuetbach added a comment - I can confirm this bug with iOS 6. Wen run into this problem and filed a bugreport: https://issues.apache.org/jira/browse/CB-1535

            People

            • Assignee:
              Shazron Abdullah
              Reporter:
              Amirudin Bin Mohamed Ghani
            • Votes:
              11 Vote for this issue
              Watchers:
              16 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development