Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Persistent Offline Storage White


Published on

Published in: Technology
  • that gzip idea is awesome.. fits in very well if you have to deal with flash based storage anyway. damn, why didn't i think earlier. thanks for sharing.. :-)
    Are you sure you want to  Yes  No
    Your message goes here
  • Hey Sumit,
    1. Here is an example of gzipping on the browser side:
    2. is not domain specific. You are not bound by the same-origin-policy when reading and writing to it. However, you cannot read and write to it from different windows.
    3. does persist yes. this is covered in the slde deck.
    Are you sure you want to  Yes  No
    Your message goes here
  • few comments/questions:
    1. how do you use gzip on the browser side? know of any utility script that can do gzip/gunzip on client side?
    2. is domain specific. meaning if a window with name 'foo' loads contents from domainA, you could still open another window with name 'foo' from a window loaded with content from domainB
    3. persists for multiple page load/navigations on the same window
    Are you sure you want to  Yes  No
    Your message goes here

Persistent Offline Storage White

  1. 1. JavaScript Persistence & Offline Storage Dec 9 2009 Alexei White (Foresee Results - Nitobi) @AlexeiRWhite
  2. 2. What is Persistence / Storage? <ul><li>Data ‘locker’ that persists between page loads, and/or browser sessions. </li></ul><ul><li>Client-side data storage vs Server-side storage. </li></ul><ul><li>Browsers & JavaScript engines typically do not have file I/O capabilities. </li></ul><ul><li>Many reasons to want to keep data local. </li></ul>
  3. 3. Why Persistent Storage? <ul><li>Provide sandbox mode for online documents. (eg Word vs Google Docs) </li></ul><ul><li>Persist trivial data like layout and preferences. </li></ul><ul><li>Eliminate unnecessary server requests. </li></ul><ul><li>Provide powerful data lookup capabilities (SQL) to JavaScript apps. </li></ul><ul><li>Browser crash fail-safe / offline mode. </li></ul><ul><li>Cacheing scripts. </li></ul>
  4. 4. Offline Storage Use Case
  5. 5. Isn’t That What Cookies are For? <ul><li>Very limited storage capacity (4000 bytes per) </li></ul><ul><li>Limited # of cookies. (~20 max per domain, ~300 cookies max overall) </li></ul><ul><li>Sent to server on every request. </li></ul><ul><li>Useful storage needs to be in 100k+ range contiguous. </li></ul>
  6. 6. The Flavors of JS Persistence
  7. 7. Storage Flavors
  8. 8. <ul><li>Very old string property of the browser’s window object. </li></ul><ul><li>Used primarily for setting hyperlink targets. </li></ul><ul><li>Persistent across pages and domains. </li></ul><ul><li>Can be used before domready event. </li></ul>
  9. 9. <ul><li>Combine with JSON lib or native code for reading and writing: </li></ul>// Write a structure to var myObj = { “a”:”hello world”, “b”:324234 }; = JSON.stringify(myObj); // Read it back: var myObj; try { myObj = JSON.parse( ); } catch(e) {}
  10. 10. <ul><li>Completely insecure. </li></ul><ul><ul><li>Same Origin Policy does not apply. </li></ul></ul><ul><ul><li>Data stored in plain text within the DOM. </li></ul></ul><ul><ul><li>Can be read outside your website. </li></ul></ul><ul><li>Tends to degrade browser performance a bit. </li></ul><ul><ul><li>2MB upper limit FF or starts to get slow. </li></ul></ul><ul><ul><li>4MB IE same. </li></ul></ul><ul><li>Not Crash-safe. </li></ul><ul><ul><li>Wont be restored even if tabs are restored after crash. </li></ul></ul><ul><ul><li>Not written to disk. </li></ul></ul><ul><li>Great place to cache trivial data or communicate inter-app. </li></ul>
  11. 11. Flash Local Shared Object <ul><li>Key/Value pair storage object built into Flash player 6+. </li></ul><ul><li>Up to 100K free. Afterward, dialogue appears asking user for permission to save more. </li></ul><ul><li>Supported by virtually all browsers via ExternalInterface: </li></ul><ul><ul><li>IE5+ </li></ul></ul><ul><ul><li>Netscape 8+ </li></ul></ul><ul><ul><li>Firefox 1+ </li></ul></ul><ul><ul><li>Safari 1.3+ </li></ul></ul><ul><ul><li>Opera 9+ </li></ul></ul>
  12. 12. Flash Local Shared Object <ul><li>Step 1: Create a new Flash movie: </li></ul>import flash.external.ExternalInterface; // Saves data to datastore function saveData(store, key, value) { sharedObject = SharedObject.getLocal(store);[key] = value; sharedObject.flush(); } // Retrieves data function loadDate(store, key) { return SharedObject.getLocal(store).data[key]; } ExternalInterface.addCallback(“saveData”, this.saveData); ExternalInterface.addCallback(“loadData”, this.loadData);
  13. 13. Flash Local Shared Object <ul><li>Step 2: Embed the movie (manually or via SwfObject) </li></ul><object classid=“bla” codebase=“bla” height=“1” width=“1” id=“storageMovie”> <param name=“movie” value=“sharedobject.swf” /> <param name=“allowScriptAccess” value=“always” /> <embed src=“shredobject.swf” allowScriptAccess=“always” width=“1” height=“1” name=“storageMovie” /> </object>
  14. 14. Flash Local Shared Object <ul><li>Step 3: Communicate via ExternalInterface </li></ul>// Save $(‘storageMovie’).saveData(store,key,value); // Load var result = $(‘storageMovie’).loadData(store, key);
  15. 15. Flash Local Shared Object <ul><li>Gotchas: </li></ul><ul><ul><li>Flash movie must be on visible portion of screen at least once before accessing via ExternalInterface. </li></ul></ul><ul><ul><li>If it’s not working: </li></ul></ul><ul><ul><ul><li>Check that the movie did load. </li></ul></ul></ul><ul><ul><ul><li>It’s on visible portion of screen. </li></ul></ul></ul><ul><ul><ul><li>document.getElementById(movieId) returns an object. </li></ul></ul></ul><ul><ul><ul><li>allowScriptAccess = “always” </li></ul></ul></ul>
  16. 16. The Lowest Common Denominator <ul><li>Flash Local Shared Object </li></ul><ul><ul><li>ExternalInterface supported by all browsers. </li></ul></ul><ul><ul><li>Provides persistent offline + crash-safe support. </li></ul></ul><ul><ul><li>Has wide adoption on web. </li></ul></ul><ul><ul><li>Provides decent (~100K+) storage capacity*. </li></ul></ul><ul><ul><li>Not wiped when user clears browser cache. </li></ul></ul>* When combined with GZIP.
  17. 17. Silverlight IsolatedStorage <ul><li>Silverlight has same functionality. </li></ul><ul><li>More capacity (1024 KB vs 100 KB). </li></ul><ul><li>Binary storage format </li></ul><ul><li>Streamwriters / readers </li></ul><ul><li>Compression </li></ul> System.IO.IsolatedStorage.IsolatedStorageFile
  18. 18. Silverlight IsolatedStorage using System.IO.IsolatedStorage.IsolatedStorageFile; IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();    if(store.FileExists(FILENAME)){        isfs = new IsolatedStorageFileStream(FILENAME, FileMode.OpenOrCreate, store);        StreamReader streamReader = new StreamReader(isfs);        string s;        while ((s = streamReader.ReadLine()) != null)            TextArea.Text += (s + ' ');        streamReader.Close();    }      // save data to local storage    IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();    IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(FILENAME, FileMode.OpenOrCreate, store);    StreamWriter streamWriter = new StreamWriter(isfs);    streamWriter.Write(&quot;New Text&quot;);    streamWriter.Flush();    streamWriter.Close();
  19. 19. HTML5 Overview <ul><li>Next big update to HTML standard. </li></ul><ul><li>AKA “Web Applications 1.0”. </li></ul><ul><li>In “Last Call” state with WHATWG. </li></ul><ul><li>Not necessarily the future of web*. </li></ul><ul><li>New stuff: </li></ul><ul><ul><li>Canvas tag </li></ul></ul><ul><ul><li>Rich media (video) </li></ul></ul><ul><ul><li>Storage </li></ul></ul><ul><ul><li>Doc editing </li></ul></ul><ul><ul><li>Drag and Drop </li></ul></ul><ul><ul><li>Cross-doc messaging </li></ul></ul><ul><ul><li>History management </li></ul></ul><ul><ul><li>MIME and protocol reg. </li></ul></ul>
  20. 20. HTML5 Features In Jeopardy <ul><li>Canvas tag </li></ul><ul><ul><li>Microsoft has VML & possibly SVG in IE9 </li></ul></ul><ul><li>DOM WebDB (SQL based storage) </li></ul><ul><ul><li>No for IE (lots of reasons why) </li></ul></ul><ul><ul><li>Probably not for Mozilla </li></ul></ul><ul><li>Media embedding </li></ul><ul><ul><li>No for IE * </li></ul></ul><ul><ul><li>Confusion over codecs (H.264 / Ogg Theora) </li></ul></ul><ul><ul><li>Concern over Patent litigation. </li></ul></ul>
  21. 21. HTML5 Storage Overview <ul><li>Two kinds of storage proposed: </li></ul><ul><ul><li>Key/value pair (hash) storage </li></ul></ul><ul><ul><ul><li>Create expando properties on storage object. </li></ul></ul></ul><ul><ul><ul><li>Similar to Shared Local Object in flash. </li></ul></ul></ul><ul><ul><li>WebDB (SQLite based) </li></ul></ul><ul><ul><ul><li>Create and populate databases right in the browser </li></ul></ul></ul><ul><ul><ul><li>Perform SQL queries on the fly. </li></ul></ul></ul><ul><ul><ul><li>Based on SQLite. </li></ul></ul></ul>
  22. 22. HTML5 DOM Storage <ul><li>Hash-based storage of strings (not objects). </li></ul><ul><li>10 MB per zone. </li></ul><ul><li>Two kinds: </li></ul><ul><ul><li>sessionStorage: </li></ul></ul><ul><ul><ul><li>Die when browser closes </li></ul></ul></ul><ul><ul><ul><li>Not shared between tabs </li></ul></ul></ul><ul><ul><li>localStorage </li></ul></ul><ul><ul><ul><li>Crash-safe </li></ul></ul></ul><ul><ul><ul><li>Shared BW tabs / windows and sessions – but not zones. </li></ul></ul></ul>
  23. 23. HTML5 DOM Storage <ul><li>Reading and writing: </li></ul><ul><li>Won’t work: </li></ul>// Writing data sessionStorage.myKey = “Hello”; window.sessionStorage[“myKey”] = “Hello”; window.localStorage.myKey = “Hello”; localStorage[“myKey”] = “Hello”; sessionStorage.myObj = {a:true, b:false}; console.log(sessionStorage.myObj) // “[Object object]”
  24. 24. HTML5 DOM Storage <ul><li>Events (onstorage, onstoragecommit*): </li></ul>function handleStorageEvent(e) { // These attributes only appear in Safari var str = “Key: “ + e.key + “ ”; str += “Original Value: “ + e.oldValue + “ ”; str += “New Value: “ + e.newValue; alert(str); } // Bindings, IE then W3C if (document.attachEvent) document.attachEvent(“onstorage”, handleStorageEvent); else document.body.addEventListener(“storage”, handleStorageEvent); *IE8 only
  25. 25. HTML5 DOM Storage <ul><li>Clearing: </li></ul><ul><li>Iterating: </li></ul><ul><li>Deleting: </li></ul>sessionStorage.clear(); for (var I = 0; I < sessionStorage.length; I++) { console.log(sessionStorage[sessionStorage.key(I)]); } sessionStorage.removeItem(“mykey”);
  26. 26. HTML5 WebDB <ul><li>Will be supported in Safari 3.1+, Opera 9.?, Chrome. </li></ul><ul><li>Around 5MB per domain. </li></ul><ul><li>Accessible across tabs and windows. </li></ul><ul><li>Basic SQLite SQL language features and types supported. </li></ul><ul><li>Schema versioning supported. </li></ul><ul><li>Transactions supported. </li></ul><ul><li>Tables must be created on first run. </li></ul>
  27. 27. HTML5 Database <ul><li>Detection: </li></ul><ul><li>Error trapping: </li></ul>if (window.openDatabase) { // … } try { // DB operations go here } catch(e) { if (e == 2) { // Version mismatch } }
  28. 28. HTML5 Database <ul><li>Simple DB Access: </li></ul><ul><li>Other parameters: </li></ul>var database = openDatabase(&quot;Database Name&quot;, &quot;Database Version&quot;); database.executeSql(&quot;SELECT * FROM test&quot;, function(result1) {    // do something with the results    database.executeSql(&quot;DROP TABLE test&quot;, function(result2) {      // do some more stuff      alert(&quot;My second database query finished executing!&quot;);    }); }); openDatabase(shortName, version, displayName, maxSize)
  29. 29. HTML5 Database <ul><li>Parameterized queries: </li></ul><ul><li>Transactions: </li></ul>transaction.executeSql(“INSERT INTO products (name, price) VALUES (?, ?);’, [“Book”, 2.01]); myDB.transaction( function(transaction) { // Create the products table transaction.executeSQL(‘CREATE TABLE products (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL DEFAULT “Widget”, price REAL NOT NULL DEFAULT 9.99);’, []); transaction.executeSql(“INSERT INTO products (name, price) VALUES (?, ?);’, [“Book”, 2.01]); } }
  30. 30. HTML5 Database <ul><li>Selects: </li></ul>db.transaction( function (transaction) { var query=&quot;SELECT * FROM products”; transaction.executeSql(query, [], handleProductsQuery, errorHandler); }, transactionErrorCallback); function handleProductsQuery(transaction, resultSet) { for (var I = 0; I < resultSet.length; I++) { var row = resultSet.rows.item(i); console.log(row[‘name’] + “: “ + row[‘price’]); } }
  31. 31. HTML5 Database <ul><li>Safari DB Inspector </li></ul>
  32. 32. Alternatives to HTML5 WebDB <ul><li>TrimQuery - </li></ul><ul><li>CouchDB </li></ul><ul><ul><li>Apache-project for RESTful JSON-based data queries. </li></ul></ul><ul><ul><li>Can solve the backend/frontend interop problem by being available to both via HTTP requests. </li></ul></ul><ul><li>Google Gears SQLite DB. Same Interface. * </li></ul><ul><li>Hash-based data storage using DOM storage or other mechanism. </li></ul>* Discontinued by Google
  33. 33. Questions? <ul><li>Slide deck at </li></ul>