Advertisement
photokandy

Persistent Storage for localStorage under iOS5.1b3 phonegap

Feb 3rd, 2012
2,244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // localStorage loading & saving
  3. //
  4. // Turns out that under iOS 5.1 (b3), the localStorage is stored in a vulnerable location.
  5. // So, we need to ensure that the settings are consistently loaded at app startup and saved
  6. // again at periodic times. The main app will continue to use localStorage as if nothing
  7. // is wrong, but these functions will load and save the data to persistent storage.
  8. //
  9. // Author: Kerri Shotts, photoKandy Studios LLC. License: MIT.
  10. //
  11. // v2
  12. //
  13. // Added: documentation and functions to deal with non-periodic sync
  14.  
  15. /**************************************************************************
  16.  *
  17.  * persistent storage for localStorage (phonegap / iOS)
  18.  *
  19.  * These functions simply copy the data in localStorage to a persistent
  20.  * location in the documents folder named localStorage.dat. The format is
  21.  * pretty simple: each item is separated by [EOK], whilst the key/value is
  22.  * separated by [EQ]. Therefore, this is easy to break (have a key/value
  23.  * with one of these values...), but it works for my present needs.
  24.  *
  25.  * The persistentStorage object stores the read/write functions and can be
  26.  * used by calling the saveLocalStorage and loadLocalStorage functions.
  27.  *
  28.  * By default, the routine saves data to localStorage.dat at the rate of
  29.  * 30 seconds. If this is not desired, syncLocalStorageInterval should be
  30.  * reset to 0 prior to the next call to saveLocalStorage(), at which point
  31.  * the continuous saving will be stopped. At that point, it is up to you
  32.  * to call saveLocalStorage() manually.
  33.  *
  34.  */
  35.  
  36. /**
  37.  *
  38.  * syncLocalStorageInterval defines the length of time before another
  39.  * save operation can be started. 30000 = 30s.
  40.  * If you wish to disable the periodic save, set this to 0.
  41.  *
  42.  */
  43. var syncLocalStorageInterval = 30000;
  44. var consoleLogging = true;                                          // if true, log to the console
  45.  
  46. /**
  47.  *
  48.  * The persistentStorage function contains the functions necessary
  49.  * to read from and save to the localStorage.dat file in the documents
  50.  * directory.
  51.  *
  52.  */
  53. var persistentStorage = function()
  54. {
  55.     // Get self so we don't have to be funny when a timeout calls us...
  56.     var self = this;
  57.    
  58.     /**
  59.      * Called when the filesystem is successfully returned. Will attempt to get "localStorage.dat"
  60.      * access (and create it if necesssary).
  61.      */
  62.     self.gotFStoWrite = function (fileSystem)
  63.     {
  64.         fileSystem.root.getFile("localStorage.dat", {create: true, exclusive: false}, self.gotFileEntrytoWrite, self.fail);
  65.     }
  66.    
  67.     /**
  68.      *
  69.      * Called when the filesystem is successfully returned. It will attempt to open "localStorage.dat" for
  70.      * read-only access.
  71.      */
  72.     self.gotFStoRead = function (fileSystem)
  73.     {
  74.         fileSystem.root.getFile("localStorage.dat", null, self.gotFileEntrytoRead, self.fail);
  75.     }
  76.    
  77.     /**
  78.      *
  79.      * Called when localStorage.dat is obtained for writing. It will create a fileWriter
  80.      * which will actually write the contents of localStorage.
  81.      */
  82.     self.gotFileEntrytoWrite = function (fileEntry)
  83.     {
  84.         fileEntry.createWriter (self.gotFileWriter, self.fail);
  85.     }
  86.  
  87.     /**
  88.      *
  89.      * Called when localStorage.dat is obtained for reading. It will create a fileReader
  90.      * which will read the contents of the file into localStorage.
  91.      */
  92.     self.gotFileEntrytoRead = function (fileEntry)
  93.     {
  94.         fileEntry.file (self.gotFileReader, self.fail);
  95.     }
  96.    
  97.     /**
  98.      *
  99.      * Called when the file localStorage.dat is successfully opened for reading.
  100.      * Parses the file by splitting it into key/value pairs, and then splitting
  101.      * those pairs into the key and the value. It then saves them to localStorage
  102.      * using localStorage.setItem().
  103.      *
  104.      * NOTE: localStorage is /not/ cleared when this file is loaded.
  105.      */
  106.     self.gotFileReader = function (file)
  107.     {
  108.         var reader = new FileReader();
  109.         reader.onloadend = function (evt) {
  110.             if (consoleLogging) { console.log ("Syncing localStorage from persistent store."); }
  111.             var ls = evt.target.result.split("[EOK]");
  112.             for (var i=0;i<ls.length;i++)
  113.             {
  114.                 var kv = ls[i].split("[EQ]");
  115.                 localStorage.setItem ( kv[0], kv[1] );
  116.             }
  117.             if (consoleLogging) { console.log ("Sync complete."); }
  118.             if (self.readCallback)
  119.             {
  120.                 self.readCallback();
  121.             }
  122.         };
  123.         reader.readAsText (file);
  124.     }
  125.  
  126.     /**
  127.      *
  128.      * Called when localStorage.dat is open for writing and created if necessary.
  129.      * Writes out each value in localStorage as a key/value pair.
  130.      */
  131.     self.gotFileWriter = function (writer)
  132.     {
  133.         if (consoleLogging) { console.log ("Syncing localStorage to persistent store."); }
  134.        
  135.         var s = "";
  136.        
  137.         for (var i=0; i<localStorage.length; i++)
  138.         {
  139.             var key = localStorage.key(i);
  140.             var value = localStorage[key];
  141.             s = s + key + "[EQ]" + value + "[EOK]";
  142.         }
  143.         writer.write ( s );
  144.        
  145.         if (consoleLogging) { console.log ("Sync Complete."); }
  146.        
  147.         if (self.writeCallback)
  148.         {
  149.             self.writeCallback();
  150.         }
  151.     }
  152.  
  153.     /**
  154.      *
  155.      * If an error should occur during a read or write operation,
  156.      * we will display the error. If a readCallback() is defined,
  157.      * call it.
  158.      */
  159.     self.fail = function (error)
  160.     {
  161.         console.log ("Error: " + error.code);
  162.             if (self.readCallback)
  163.             {
  164.                 self.readCallback();
  165.             }
  166.     }
  167.  
  168.     /**
  169.      *
  170.      * Kicks off a save operation. If callback is specified,
  171.      * it is called when the save operation is complete.
  172.      */
  173.     self.write = function ( callback )
  174.     {
  175.         if (callback)
  176.         {
  177.             self.writeCallback = callback;
  178.         }
  179.         window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, self.gotFStoWrite, self.fail);
  180.     }
  181.    
  182.     /**
  183.      *
  184.      * Kicks off a read operation. if callback is defined,
  185.      * it is called when the operation is complete OR a read error
  186.      * occurs.
  187.      */
  188.     self.read = function( callback )
  189.     {
  190.         if (callback)
  191.         {
  192.             self.readCallback = callback;
  193.         }
  194.         window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, self.gotFStoRead, self.fail);
  195.     }
  196. }
  197.  
  198. /**
  199.  *
  200.  * Saves localStorage to the persistent store in localStorage.dat in the documents folder.
  201.  *
  202.  * If callback is defined, it is executed when the save operation is complete. If
  203.  * syncLocalStorageInterval is greater than zero, a timeout is created in order to
  204.  * call saveLocalStorage again, essentially creating a repeating save.
  205.  */
  206. function saveLocalStorage( callback )
  207. {
  208.     var self = this;
  209.     var o = new persistentStorage();
  210.     self.callback = callback;
  211.     o.write(function()
  212.             {
  213.                 if (syncLocalStorageInterval>0)
  214.                 {
  215.                     setTimeout (saveLocalStorage, syncLocalStorageInterval);    
  216.                 }
  217.                 if (self.callback) { self.callback(); self.callback = null; }
  218.             });
  219.    
  220. }
  221.  
  222. /**
  223.  *
  224.  * Loads the localStorage data from the Documents/localStorage.dat file.
  225.  *
  226.  * If callback is defined, it is called after the load is complete or an
  227.  * error occurs.
  228.  */
  229. function loadLocalStorage( callback )
  230. {
  231.     var o = new persistentStorage();
  232.     o.read( callback );
  233. }
  234.  
  235. /**
  236.  *
  237.  * This one kicks everything off. It calls loadLocalStorage to load the
  238.  * localStorage data from the persistent store, and then, if syncLocalStorageInterval
  239.  * is greater than zero, sets up the next save operation.
  240.  *
  241.  * If callback is defined, it is called after the read is complete or an
  242.  * error occurs. Useful for defining when the application should start (as it should
  243.  * load the store completely before beginning.)
  244.  */
  245. function loadLocalStorageAndSync( callback )
  246. {
  247.     var self = this;
  248.     self.callback = callback;
  249.  
  250.     loadLocalStorage(function()
  251.                      {  
  252.                         if (syncLocalStorageInterval>0)
  253.                         {
  254.                             setTimeout (saveLocalStorage, syncLocalStorageInterval);
  255.                         }
  256.                         if (self.callback) { self.callback(); self.callback = null; }
  257.                      });
  258. }
  259.  
  260. // to kick start it, just do: (we give 500ms for the filesystem to become ready)
  261. // startApp below is the name of your startup routines.
  262.         setTimeout (function()
  263.                     {
  264.                        loadLocalStorageAndSync ( startApp ); // start the app after we load the settings!
  265.                     }, 500); // kick off a load in 500ms
  266.  
  267. //
  268. // If you want to manage saving manually (instead of every 30s), do this:
  269. syncLocalStorageInterval = 0;          // turn off periodic save
  270. ...
  271. localStorage.setItem ("Key", "Value"); // save something to localStorage
  272. saveLocalStorage();                    // save localStorage to persistent storage
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement