[483] | 1 | dojo.provide("dojox.storage.manager"); |
---|
| 2 | //dojo.require("dojo.AdapterRegistry"); |
---|
| 3 | // FIXME: refactor this to use an AdapterRegistry |
---|
| 4 | |
---|
| 5 | dojox.storage.manager = new function(){ |
---|
| 6 | // summary: |
---|
| 7 | // A singleton class in charge of the dojox.storage system |
---|
| 8 | // description: |
---|
| 9 | // Initializes the storage systems and figures out the best available |
---|
| 10 | // storage options on this platform. |
---|
| 11 | |
---|
| 12 | // currentProvider: Object |
---|
| 13 | // The storage provider that was automagically chosen to do storage |
---|
| 14 | // on this platform, such as dojox.storage.FlashStorageProvider. |
---|
| 15 | this.currentProvider = null; |
---|
| 16 | |
---|
| 17 | // available: Boolean |
---|
| 18 | // Whether storage of some kind is available. |
---|
| 19 | this.available = false; |
---|
| 20 | |
---|
| 21 | // providers: Array |
---|
| 22 | // Array of all the static provider instances, useful if you want to |
---|
| 23 | // loop through and see what providers have been registered. |
---|
| 24 | this.providers = []; |
---|
| 25 | |
---|
| 26 | this._initialized = false; |
---|
| 27 | |
---|
| 28 | this._onLoadListeners = []; |
---|
| 29 | |
---|
| 30 | this.initialize = function(){ |
---|
| 31 | // summary: |
---|
| 32 | // Initializes the storage system and autodetects the best storage |
---|
| 33 | // provider we can provide on this platform |
---|
| 34 | this.autodetect(); |
---|
| 35 | }; |
---|
| 36 | |
---|
| 37 | this.register = function(/*string*/ name, /*Object*/ instance){ |
---|
| 38 | // summary: |
---|
| 39 | // Registers the existence of a new storage provider; used by |
---|
| 40 | // subclasses to inform the manager of their existence. The |
---|
| 41 | // storage manager will select storage providers based on |
---|
| 42 | // their ordering, so the order in which you call this method |
---|
| 43 | // matters. |
---|
| 44 | // name: |
---|
| 45 | // The full class name of this provider, such as |
---|
| 46 | // "dojox.storage.FlashStorageProvider". |
---|
| 47 | // instance: |
---|
| 48 | // An instance of this provider, which we will use to call |
---|
| 49 | // isAvailable() on. |
---|
| 50 | |
---|
| 51 | // keep list of providers as a list so that we can know what order |
---|
| 52 | // storage providers are preferred; also, store the providers hashed |
---|
| 53 | // by name in case someone wants to get a provider that uses |
---|
| 54 | // a particular storage backend |
---|
| 55 | this.providers.push(instance); |
---|
| 56 | this.providers[name] = instance; |
---|
| 57 | }; |
---|
| 58 | |
---|
| 59 | this.setProvider = function(storageClass){ |
---|
| 60 | // summary: |
---|
| 61 | // Instructs the storageManager to use the given storage class for |
---|
| 62 | // all storage requests. |
---|
| 63 | // example: |
---|
| 64 | // | dojox.storage.setProvider( |
---|
| 65 | // | dojox.storage.IEStorageProvider) |
---|
| 66 | |
---|
| 67 | }; |
---|
| 68 | |
---|
| 69 | this.autodetect = function(){ |
---|
| 70 | // summary: |
---|
| 71 | // Autodetects the best possible persistent storage provider |
---|
| 72 | // available on this platform. |
---|
| 73 | |
---|
| 74 | //console.debug("dojox.storage.manager.autodetect"); |
---|
| 75 | |
---|
| 76 | if(this._initialized){ // already finished |
---|
| 77 | return; |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | // a flag to force the storage manager to use a particular |
---|
| 81 | // storage provider type, such as |
---|
| 82 | // djConfig = {forceStorageProvider: "dojox.storage.WhatWGStorageProvider"}; |
---|
| 83 | var forceProvider = dojo.config["forceStorageProvider"] || false; |
---|
| 84 | |
---|
| 85 | // go through each provider, seeing if it can be used |
---|
| 86 | var providerToUse; |
---|
| 87 | //FIXME: use dojo.some |
---|
| 88 | for(var i = 0; i < this.providers.length; i++){ |
---|
| 89 | providerToUse = this.providers[i]; |
---|
| 90 | if(forceProvider && forceProvider == providerToUse.declaredClass){ |
---|
| 91 | // still call isAvailable for this provider, since this helps some |
---|
| 92 | // providers internally figure out if they are available |
---|
| 93 | // FIXME: This should be refactored since it is non-intuitive |
---|
| 94 | // that isAvailable() would initialize some state |
---|
| 95 | providerToUse.isAvailable(); |
---|
| 96 | break; |
---|
| 97 | }else if(!forceProvider && providerToUse.isAvailable()){ |
---|
| 98 | break; |
---|
| 99 | } |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | if(!providerToUse){ // no provider available |
---|
| 103 | this._initialized = true; |
---|
| 104 | this.available = false; |
---|
| 105 | this.currentProvider = null; |
---|
| 106 | console.warn("No storage provider found for this platform"); |
---|
| 107 | this.loaded(); |
---|
| 108 | return; |
---|
| 109 | } |
---|
| 110 | |
---|
| 111 | // create this provider and mix in it's properties |
---|
| 112 | // so that developers can do dojox.storage.put rather |
---|
| 113 | // than dojox.storage.currentProvider.put, for example |
---|
| 114 | this.currentProvider = providerToUse; |
---|
| 115 | dojo.mixin(dojox.storage, this.currentProvider); |
---|
| 116 | |
---|
| 117 | // have the provider initialize itself |
---|
| 118 | dojox.storage.initialize(); |
---|
| 119 | |
---|
| 120 | this._initialized = true; |
---|
| 121 | this.available = true; |
---|
| 122 | }; |
---|
| 123 | |
---|
| 124 | this.isAvailable = function(){ /*Boolean*/ |
---|
| 125 | // summary: |
---|
| 126 | // Returns whether any storage options are available. |
---|
| 127 | return this.available; |
---|
| 128 | }; |
---|
| 129 | |
---|
| 130 | this.addOnLoad = function(func){ /* void */ |
---|
| 131 | // summary: |
---|
| 132 | // Adds an onload listener to know when Dojo Offline can be used. |
---|
| 133 | // description: |
---|
| 134 | // Adds a listener to know when Dojo Offline can be used. This |
---|
| 135 | // ensures that the Dojo Offline framework is loaded and that the |
---|
| 136 | // local dojox.storage system is ready to be used. This method is |
---|
| 137 | // useful if you don't want to have a dependency on Dojo Events |
---|
| 138 | // when using dojox.storage. |
---|
| 139 | // func: Function |
---|
| 140 | // A function to call when Dojo Offline is ready to go |
---|
| 141 | this._onLoadListeners.push(func); |
---|
| 142 | |
---|
| 143 | if(this.isInitialized()){ |
---|
| 144 | this._fireLoaded(); |
---|
| 145 | } |
---|
| 146 | }; |
---|
| 147 | |
---|
| 148 | this.removeOnLoad = function(func){ /* void */ |
---|
| 149 | // summary: |
---|
| 150 | // Removes the given onLoad listener |
---|
| 151 | for(var i = 0; i < this._onLoadListeners.length; i++){ |
---|
| 152 | if(func == this._onLoadListeners[i]){ |
---|
| 153 | this._onLoadListeners.splice(i, 1); |
---|
| 154 | break; |
---|
| 155 | } |
---|
| 156 | } |
---|
| 157 | }; |
---|
| 158 | |
---|
| 159 | this.isInitialized = function(){ /*Boolean*/ |
---|
| 160 | // summary: |
---|
| 161 | // Returns whether the storage system is initialized and ready to |
---|
| 162 | // be used. |
---|
| 163 | |
---|
| 164 | // FIXME: This should REALLY not be in here, but it fixes a tricky |
---|
| 165 | // Flash timing bug. |
---|
| 166 | // Confirm that this is still needed with the newly refactored Dojo |
---|
| 167 | // Flash. Used to be for Internet Explorer. -- Brad Neuberg |
---|
| 168 | if(this.currentProvider != null |
---|
| 169 | && this.currentProvider.declaredClass == "dojox.storage.FlashStorageProvider" |
---|
| 170 | && dojox.flash.ready == false){ |
---|
| 171 | return false; |
---|
| 172 | }else{ |
---|
| 173 | return this._initialized; |
---|
| 174 | } |
---|
| 175 | }; |
---|
| 176 | |
---|
| 177 | this.supportsProvider = function(/*string*/ storageClass){ /* Boolean */ |
---|
| 178 | // summary: |
---|
| 179 | // Determines if this platform supports the given storage provider. |
---|
| 180 | // example: |
---|
| 181 | // | dojox.storage.manager.supportsProvider( |
---|
| 182 | // | "dojox.storage.InternetExplorerStorageProvider"); |
---|
| 183 | |
---|
| 184 | // construct this class dynamically |
---|
| 185 | try{ |
---|
| 186 | // dynamically call the given providers class level isAvailable() |
---|
| 187 | // method |
---|
| 188 | var provider = eval("new " + storageClass + "()"); |
---|
| 189 | var results = provider.isAvailable(); |
---|
| 190 | if(!results){ return false; } |
---|
| 191 | return results; |
---|
| 192 | }catch(e){ |
---|
| 193 | return false; |
---|
| 194 | } |
---|
| 195 | }; |
---|
| 196 | |
---|
| 197 | this.getProvider = function(){ /* Object */ |
---|
| 198 | // summary: |
---|
| 199 | // Gets the current provider |
---|
| 200 | return this.currentProvider; |
---|
| 201 | }; |
---|
| 202 | |
---|
| 203 | this.loaded = function(){ |
---|
| 204 | // summary: |
---|
| 205 | // The storage provider should call this method when it is loaded |
---|
| 206 | // and ready to be used. Clients who will use the provider will |
---|
| 207 | // connect to this method to know when they can use the storage |
---|
| 208 | // system. You can either use dojo.connect to connect to this |
---|
| 209 | // function, or can use dojox.storage.manager.addOnLoad() to add |
---|
| 210 | // a listener that does not depend on the dojo.event package. |
---|
| 211 | // example: |
---|
| 212 | // | if(dojox.storage.manager.isInitialized() == false){ |
---|
| 213 | // | dojo.connect(dojox.storage.manager, "loaded", TestStorage, "initialize"); |
---|
| 214 | // | }else{ |
---|
| 215 | // | dojo.connect(dojo, "loaded", TestStorage, "initialize"); |
---|
| 216 | // | } |
---|
| 217 | // example: |
---|
| 218 | // | dojox.storage.manager.addOnLoad(someFunction); |
---|
| 219 | |
---|
| 220 | |
---|
| 221 | // FIXME: we should just provide a Deferred for this. That way you |
---|
| 222 | // don't care when this happens or has happened. Deferreds are in Base |
---|
| 223 | this._fireLoaded(); |
---|
| 224 | }; |
---|
| 225 | |
---|
| 226 | this._fireLoaded = function(){ |
---|
| 227 | //console.debug("dojox.storage.manager._fireLoaded"); |
---|
| 228 | |
---|
| 229 | dojo.forEach(this._onLoadListeners, function(i){ |
---|
| 230 | try{ |
---|
| 231 | i(); |
---|
| 232 | }catch(e){ console.debug(e); } |
---|
| 233 | }); |
---|
| 234 | }; |
---|
| 235 | |
---|
| 236 | this.getResourceList = function(){ |
---|
| 237 | // summary: |
---|
| 238 | // Returns a list of whatever resources are necessary for storage |
---|
| 239 | // providers to work. |
---|
| 240 | // description: |
---|
| 241 | // This will return all files needed by all storage providers for |
---|
| 242 | // this particular environment type. For example, if we are in the |
---|
| 243 | // browser environment, then this will return the hidden SWF files |
---|
| 244 | // needed by the FlashStorageProvider, even if we don't need them |
---|
| 245 | // for the particular browser we are working within. This is meant |
---|
| 246 | // to faciliate Dojo Offline, which must retrieve all resources we |
---|
| 247 | // need offline into the offline cache -- we retrieve everything |
---|
| 248 | // needed, in case another browser that requires different storage |
---|
| 249 | // mechanisms hits the local offline cache. For example, if we |
---|
| 250 | // were to sync against Dojo Offline on Firefox 2, then we would |
---|
| 251 | // not grab the FlashStorageProvider resources needed for Safari. |
---|
| 252 | var results = []; |
---|
| 253 | dojo.forEach(dojox.storage.manager.providers, function(currentProvider){ |
---|
| 254 | results = results.concat(currentProvider.getResourceList()); |
---|
| 255 | }); |
---|
| 256 | |
---|
| 257 | return results; |
---|
| 258 | } |
---|
| 259 | }; |
---|