emscripten Humble Cloud interface
Edward Rudd
2014-09-15 7102c392dafdecacff162a1eb15ae3ec5248d417

enable basic indexed DB storage of async fetched assets..

  • can be scoped (e.g. by application token)
2 files modified
113 ■■■■■ changed files
client/library/library_humble.js 110 ●●●●● patch | view | raw | blame | history
client/test/shell.html 3 ●●●●● patch | view | raw | blame | history
client/library/library_humble.js
@@ -4,13 +4,13 @@
        options: {
            // allows altering the incoming URL before it is fetched from the network
            locateAsset: null, // function(path) { return path; }
            // takes a string key and returns a modified key. return null to NOT cache the specific resource
            // returns a key for the specified path. return null to NOT cache the specific resource
            // for scoped keys..  return { scope: 'deadbeef', path: 'path' }, otherwise just return a string
            buildCacheKey: null, // function(path) { return path; }
            // function returning a hash like {width: 800, height: 600, locked: true}
            // locked specifies whether the game should ONLY use that width/height
            playerSize: null // function() { return { width: 800, height: 600, locked: true } }
        },
        /**
         * allows configuring the HUMBLE_API  simply call this method in a preRun to initialize..
         * any option is accepted and will be added to the configuration hash.
@@ -38,19 +38,107 @@
            }
        },
        storeToCache: function(path, byteArray, ondone) {
            if (path !== null) {
                HUMBLE_API.file_cache[path] = byteArray;
        pathToKey: function(path) {
            if (typeof path == 'string') {
                return { path: path, scope: '', key: ':' + path};
            } else {
                return { path: path.path, scope: path.scope, key: path.scope + ':' + path.path };
            }
            ondone(null);
        },
        storeToCache: function(path, byteArray, ondone) {
            if (path === null) {
                return ondone(null);
            }
            HUMBLE_API.getDB(function(err, db) {
                if (err) return ondone(err);
                var transaction = db.transaction([HUMBLE_API.DB_ASYNC_CACHE_STORE], 'readwrite');
                transaction.onerror = function() { ondone(this.error); };
                var store = transaction.objectStore(HUMBLE_API.DB_ASYNC_CACHE_STORE);
                var data = HUMBLE_API.pathToKey(path);
                data['data'] = byteArray;
                var req = store.put(data);
                req.onsuccess = function(e) {
                    ondone(null);
                };
                req.onerror = function() { ondone(this.error); };
            });
        },
        fetchFromCache: function(path, ondone, onfail) {
            if (path !== null && path in HUMBLE_API.file_cache) {
                ondone(HUMBLE_API.file_cache[path]);
            } else {
                // NULL for file not cached.  Error object otherwise
                onfail(null);
            if (path === null) {
                return onfail(null);
            }
            HUMBLE_API.getDB(function(err, db) {
                if (err) return onfail(err);
                var transaction = db.transaction([HUMBLE_API.DB_ASYNC_CACHE_STORE], 'readonly');
                transaction.onerror = function() { onfail(this.error); };
                var store = transaction.objectStore(HUMBLE_API.DB_ASYNC_CACHE_STORE);
                var data = HUMBLE_API.pathToKey(path);
                var req = store.get(data.key);
                req.onsuccess = function(e) {
                    if (e.target.result) {
                        var o = e.target.result;
                        ondone(o.data);
                    } else {
                        onfail(null);
                    }
                };
                req.onerror = function() { onfail(this.error); };
            });
        },
        /* indexedDB access */
        // borrowed from IDBFS
        dbs: {},
        indexedDB: function() {
            if (typeof indexedDB !== 'undefined') return indexedDB;
            var ret = null;
            if (typeof window === 'object') ret = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
            assert(ret, 'IDBFS used, but indexedDB not supported');
            return ret;
        },
        DB_VERSION: 1,
        DB_NAME: 'HUMBLE_API',
        DB_ASYNC_CACHE_STORE: 'HUMBLE_API_ASYNC',
        getDB: function(callback) {
            var db = HUMBLE_API.dbs[HUMBLE_API.DB_NAME];
            if (db) {
                return callback(null, db);
            }
            var req;
            try {
                req = HUMBLE_API.indexedDB().open(HUMBLE_API.DB_NAME, HUMBLE_API.DB_VERSION)
            } catch (e) {
                return callback(e);
            }
            req.onupgradeneeded = function(e) {
                var db = e.target.result;
                var fileStore;
                // Just replace it for now
                fileStore = db.createObjectStore(HUMBLE_API.DB_ASYNC_CACHE_STORE, {keyPath: 'key'});
                fileStore.createIndex('scope','scope',{ unique: false });
            };
            req.onsuccess = function() {
                db = req.result;
                HUMBLE_API.dbs[HUMBLE_API.DB_NAME] = db;
                callback(null, db);
            };
            req.onerror = function() {
                callback(this.error);
            };
        }
    },
    humble_init__deps: ['$CLOUDFS'],
client/test/shell.html
@@ -1304,6 +1304,9 @@
          // configure HUMBLE_API
          HUMBLE_API.configure({
              applicationtoken: 'deadbeef',
              buildCacheKey: function(path) {
                  return path;
              },
              playerSize: function() {
                  return {
                      width: 800, height: 600, locked: true