Show
Ignore:
Timestamp:
06/01/07 23:47:31 (20 months ago)
Author:
BradNeuberg
Message:

Building up code to handle if user presses the Deny button for Google Gears during a core operation so that we can fail fast and have an appropriate UI response

Location:
branches/dot_experiment
Files:
7 modified

Legend:

Unmodified
Added
Removed
  • branches/dot_experiment/src/off.js

    r8870 r8875  
    4444        goingOnline: false, 
    4545         
    46         // coreSaveFailed: boolean 
     46        // coreOperationFailed: boolean 
    4747        //      A flag set by the Dojo Offline framework that indicates 
    48         //      that saving a piece of important core data failed. This 
    49         //      flag causes a 'fail fast' condition, turning off offline 
    50         //      ability. 
    51         coreSaveFailed: false, 
     48        //      that the user denied some operation that required the 
     49        //      offline cache or an operation failed in some critical 
     50        //      way that was unrecoverable. For example, if the offline cache is 
     51        //      Google Gears and we try to get a Gears database, a 
     52        //      popup window appears asking the user whether they 
     53        //      will approve or deny this request. If the user denies 
     54        //      the request, and we are doing some operation that is 
     55        //      core to Dojo Offline, then we set this flag to 'true'.  
     56        //      This flag causes a 'fail fast' condition, turning off  
     57        //      offline ability. 
     58        coreOperationFailed: false, 
    5259         
    5360        // doNetworkChecking: boolean 
     
    177184                //      Causes the Dojo Offline framework to load its configuration data 
    178185                //      from local storage 
    179                 dojo.sync.load(finishedCallback); 
     186                //dojo.sync.load(finishedCallback); 
    180187        }, 
    181188         
     
    226233                //      normal data being saved for offline access. Dojo Offline will 
    227234                //      'fail fast' if some core piece of data could not be saved, automatically 
    228                 //      setting dojo.off.coreSaveFailed to 'true' and dojo.off.enabled to 'false'. 
     235                //      setting dojo.off.coreOperationFailed to 'true' and dojo.off.enabled to 'false'. 
    229236                // status: dojo.storage.SUCCESS, dojo.storage.PENDING, dojo.storage.FAILED 
    230237                //      Whether the save succeeded, whether it is pending based on a UI dialog 
     
    238245                //      into, such as "default", "Documents", "Contacts", etc. Optional. 
    239246                if(isCoreSave == true && status == dojo.storage.FAILED){ 
    240                         dojo.off.coreSaveFailed = true; 
    241                         dojo.off.enabled = false; 
     247                        dojo.off.coreOperationFailed = true; 
     248                        dojo.off.enabledabled = false; 
    242249                         
    243250                        // FIXME: Stop the background network thread 
     251                        dojo.off.onCoreOperationFailed(); 
    244252                } 
    245253        }, 
     
    256264        }, 
    257265         
     266        onCoreOperationFailed: function(){ 
     267                // summary: 
     268                //      Called when a core operation during interaction with the 
     269                //      offline cache is denied by the user. Some offline caches, 
     270                //      such as Google Gears, prompts the user to approve or deny 
     271                //      caching files, using the database, and more. If the user  
     272                //      denies a request that is core to Dojo Offline's operation, 
     273                //      we set dojo.off.coreOperationFailed to true and call this 
     274                //      method for listeners that would like to respond some how 
     275                //      to Dojo Offline 'failing fast'. 
     276        }, 
     277         
    258278        standardSaveHandler: function(status, isCoreSave, dataStore, item){ 
    259279                // summary: 
     
    264284                if(status == dojo.storage.FAILED 
    265285                        && isCoreSave == true){ 
    266                         this.coreSaveFailed = true; 
     286                        this.coreOperationFailed = true; 
    267287                        this.enabled = false;    
    268288                } 
     
    281301         
    282302        _onLoad: function(){ 
    283                 //dojo.debug("dojo.off._onLoad"); 
     303                dojo.debug("dojo.off._onLoad"); 
    284304                // both local storage and the page are finished loading 
    285305                 
     
    309329         
    310330        _onOfflineCacheChecked: function(){ 
     331                dojo.debug("dojo.off._onOfflineCacheChecked"); 
    311332                // this method is part of our _onLoad series of startup tasks 
     333                dojo.debug("hasOfflineCache="+this.hasOfflineCache); 
    312334                 
    313335                // if we have an offline cache, see if we have been added to the  
    314336                // list of available offline web apps yet 
    315                 if(this.hasOfflineCache == true){ 
     337                if(this.hasOfflineCache == true && this.enabled == true){ 
    316338                        // load framework data; when we are finished, continue 
    317339                        // initializing ourselves 
    318340                        this.load(dojo.lang.hitch(this, this._finishStartingUp)); 
     341                }else if(this.hasOfflineCache == true && this.enabled == false){ 
     342                        // we have an offline cache, but it is disabled for some reason 
     343                        // perhaps due to the user denying a core operation 
     344                        this._finishStartingUp(); 
    319345                }else{ 
    320346                        this._keepCheckingUntilInstalled(); 
     
    329355                // installed since this page loaded 
    330356                         
    331                 // FIXME: Gears: See if we are installed somehow 
     357                // FIXME: Gears: See if we are installed somehow after the 
     358                // page has been loaded 
    332359                 
    333360                // now continue starting up 
     
    336363         
    337364        _finishStartingUp: function(){ 
    338                 //dojo.debug("dojo.off._finishStartingUp"); 
     365                dojo.debug("dojo.off._finishStartingUp"); 
    339366                // this method is part of our _onLoad series of startup tasks 
    340367                 
    341                 // kick off a thread to check network status on 
    342                 // a regular basis 
    343                 this._startNetworkThread(); 
    344  
    345                 // try to go online 
    346                 var self = this; 
    347                 this.goOnline(function(){ 
    348                         // indicate we are ready to be used 
    349                         for(var i = 0; i < self._onLoadListeners.length; i++){ 
    350                                 self._onLoadListeners[i](); 
     368                if(this.enabled == true){ 
     369                        // kick off a thread to check network status on 
     370                        // a regular basis 
     371                        this._startNetworkThread(); 
     372 
     373                        // try to go online 
     374                        var self = this; 
     375                        this.goOnline(function(){ 
     376                                // indicate we are ready to be used 
     377                                for(var i = 0; i < self._onLoadListeners.length; i++){ 
     378                                        self._onLoadListeners[i](); 
     379                                } 
     380                        }); 
     381                }else{ // we are disabled or a core operation failed 
     382                        dojo.debug("this.coreOperationFailed="+this.coreOperationFailed); 
     383                        if(this.coreOperationFailed == true){ 
     384                                this.onCoreOperationFailed(); 
     385                        }else{ 
     386                                for(var i = 0; i < this._onLoadListeners.length; i++){ 
     387                                        this._onLoadListeners[i](); 
     388                                } 
    351389                        } 
    352                 }); 
     390                } 
    353391        }, 
    354392         
     
    367405                //dojo.debug("dojo.off._onStorageLoad"); 
    368406                this._storageLoaded = true; 
     407                 
     408                // were we able to initialize storage? if 
     409                // not, then this is a core operation, and 
     410                // let's indicate we will need to fail fast 
     411                if(dojo.storage.initialized == false){ 
     412                        dojo.debug("failed initialization!"); 
     413                        this.coreOperationFailed = true; 
     414                        this.enabled = false; 
     415                } 
    369416                 
    370417                if(this._pageLoaded == true 
  • branches/dot_experiment/src/off/files.js

    r8870 r8875  
    100100                //      with details on errors encountered. If no error occured then message is 
    101101                //      empty array with length 0. 
     102                try{ 
     103                        this.refreshing = true; 
    102104                 
    103                 this.refreshing = true; 
     105                        // get our local server 
     106                        var localServer = google.gears.factory.create("beta.localserver", "1.0"); 
     107                        var storeName = dojo.off.STORAGE_NAMESPACE + "_store"; 
    104108                 
    105                 // get our local server 
    106                 var localServer = google.gears.factory.create("beta.localserver", "1.0"); 
    107                 var storeName = dojo.off.STORAGE_NAMESPACE + "_store"; 
     109                        // refresh everything by simply removing 
     110                        // any older stores 
     111                        // FIXME: Explore whether this is truly needed - 
     112                        // workaround for versioning without using 
     113                        // Gears ManagedResourceStore 
     114                        localServer.removeStore(storeName); 
    108115                 
    109                 // refresh everything by simply removing 
    110                 // any older stores 
    111                 // FIXME: Explore whether this is truly needed - 
    112                 // workaround for versioning without using 
    113                 // Gears ManagedResourceStore 
    114                 localServer.removeStore(storeName); 
     116                        // open/create the resource store 
     117                        localServer.openStore(storeName); 
     118                        var store = localServer.createStore(storeName); 
     119                        this._store = store; 
    115120                 
    116                 // open/create the resource store 
    117                 localServer.openStore(storeName); 
    118                 var store = localServer.createStore(storeName); 
    119                 this._store = store; 
    120                  
    121                 // add our list of files to capture 
    122                 var self = this; 
    123                 this._currentFileIndex = 0; 
    124                 this._cancelID = store.capture(this.listOfURLs, function(url, success, captureId){ 
    125                         //dojo.debug("store.capture, url="+url+", success="+success); 
    126                         if(success == false){ 
    127                                 self._cancelID = null; 
    128                                 self.refreshing = false; 
    129                                 var errorMsgs = new Array(); 
    130                                 errorMsgs.push("Unable to capture: " + url); 
    131                                 finishedCallback(true, errorMsgs); 
    132                                 return; 
    133                         }else{ 
    134                                 self._currentFileIndex++; 
     121                        // add our list of files to capture 
     122                        var self = this; 
     123                        this._currentFileIndex = 0; 
     124                        this._cancelID = store.capture(this.listOfURLs, function(url, success, captureId){ 
     125                                //dojo.debug("store.capture, url="+url+", success="+success); 
     126                                if(success == false){ 
     127                                        self._cancelID = null; 
     128                                        self.refreshing = false; 
     129                                        var errorMsgs = new Array(); 
     130                                        errorMsgs.push("Unable to capture: " + url); 
     131                                        finishedCallback(true, errorMsgs); 
     132                                        return; 
     133                                }else{ 
     134                                        self._currentFileIndex++; 
     135                                } 
     136                         
     137                                if(self._currentFileIndex >= self.listOfURLs.length){ 
     138                                        self._cancelID = null; 
     139                                        self.refreshing = false; 
     140                                        finishedCallback(false, new Array()); 
     141                                } 
     142                        }); 
     143                }catch(e){ 
     144                        this.refreshing = false; 
     145         
     146                        if(typeof e.message != "undefined"){ 
     147                                e = e.message; 
    135148                        } 
    136149                         
    137                         if(self._currentFileIndex >= self.listOfURLs.length){ 
    138                                 self._cancelID = null; 
    139                                 self.refreshing = false; 
    140                                 finishedCallback(false, new Array()); 
    141                         } 
    142                 }); 
     150                        // can't refresh files -- core operation -- 
     151                        // fail fast 
     152                        dojo.off.coreOperationFailed = true; 
     153                        dojo.off.enabled = false; 
     154                        dojo.off.onCoreOperationFailed(); 
     155                } 
    143156        }, 
    144157         
  • branches/dot_experiment/src/off/ui.js

    r8827 r8875  
    170170                // 1 second 
    171171                if(dojo.sync.autoSync == true){ 
    172                         window.setTimeout(dojo.lang.hitch(dojo.sync, dojo.sync.synchronize), 1000); 
     172                        //window.setTimeout(dojo.lang.hitch(dojo.sync, dojo.sync.synchronize), 1000); 
    173173                } 
    174174        }, 
     
    253253                // try to go online 
    254254                this._testNetwork(); 
     255        }, 
     256         
     257        onCoreOperationFailed: function(){ 
     258                // summary: 
     259                //      Called if the Dojo Offline machinery is denied 
     260                //      the ability to work with the offline cache for some 
     261                //      reason during an operation that is core to it's  
     262                //      functionality. For example, if the offline cache 
     263                //      prompts the user to give permission to cache files 
     264                //      for offline use, as Google Gears does, and the user 
     265                //      selects 'deny', then we can not continue to function. 
     266                //      We 'fail fast' in this scenario so that we are in a 
     267                //      known state. This callback is called when this occurs. 
     268                alert("Application does not have permission to use Dojo Offline"); 
    255269        }, 
    256270 
     
    665679dojo.off.onSave = dojo.lang.hitch(dojo.off.ui, dojo.off.ui.onSave); 
    666680 
    667 // register ourselves to know when an offline cached has 
     681// register ourselves to know when an offline cache has 
    668682// been installed even after the page is finished loading 
    669683dojo.off.onOfflineCacheInstalled =  
    670684                                dojo.lang.hitch(dojo.off.ui, dojo.off.ui.onOfflineCacheInstalled); 
    671685 
     686// register ourselves to know if some core operation failed 
     687// or was denied by the user 
     688dojo.off.onCoreOperationFailed = dojo.lang.hitch(dojo.off.ui,  
     689                                                                                                dojo.off.ui.onCoreOperationFailed); 
     690 
    672691// start our magic when the Dojo Offline framework is ready to go 
    673692dojo.off.addOnLoad(dojo.lang.hitch(dojo.off.ui, dojo.off.ui._initialize)); 
  • branches/dot_experiment/src/sql.js

    r8870 r8875  
    3333        //                              "somePassword", callbackFunction) 
    3434         
    35         // determine our parameters 
    36         var sql = null; 
    37         var callbackFunction = null; 
    38         var password = null; 
    39          
    40         var args = new Array(arguments.length); 
    41         for(var i = 0; i < arguments.length; i++){ 
    42                 args[i] = arguments[i]; 
    43         } 
    44          
    45         sql = args.splice(0, 1)[0]; 
    46          
    47         // does this SQL statement use the ENCRYPT or DECRYPT 
    48         // keywords? if so, extract our callbackFunction and crypto 
    49         // password 
    50         if(dojo.sql._needsEncrypt(sql) || dojo.sql._needsDecrypt(sql)){ 
    51                 callbackFunction = args.splice(args.length - 1, 1)[0]; 
    52                 password = args.splice(args.length - 1, 1)[0]; 
    53         } 
    54          
    55         // 'args' now just has the SQL parameters 
    56          
    57         // get the Gears Database object 
    58         if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
    59                 dojo.sql.db = google.gears.factory.create("beta.database", "1.0"); 
    60         } 
    61          
    62         // print out debug SQL output if the developer wants that 
    63         if(dojo.sql.debug == true){ 
    64                 dojo.sql._printDebugSQL(sql, args); 
    65         } 
    66          
    67         // handle SQL that needs encryption/decryption differently 
    68         // do we have an ENCRYPT SQL statement? if so, handle that first 
    69         if(dojo.sql._needsEncrypt(sql)){ 
    70                 dojo.sql._execEncryptSQL(sql, password, args, callbackFunction); 
    71                 return; // encrypted results will arrive asynchronously 
    72         }else if(dojo.sql._needsDecrypt(sql)){ // otherwise we have a DECRYPT statement 
    73                 dojo.sql._execDecryptSQL(sql, password, args, callbackFunction); 
    74                 return; // decrypted results will arrive asynchronously 
    75         } 
    76  
    77         // execute the SQL and get the results 
    7835        try{ 
     36                // determine our parameters 
     37                var sql = null; 
     38                var callbackFunction = null; 
     39                var password = null; 
     40         
     41                var args = new Array(arguments.length); 
     42                for(var i = 0; i < arguments.length; i++){ 
     43                        args[i] = arguments[i]; 
     44                } 
     45         
     46                sql = args.splice(0, 1)[0]; 
     47         
     48                // does this SQL statement use the ENCRYPT or DECRYPT 
     49                // keywords? if so, extract our callbackFunction and crypto 
     50                // password 
     51                if(dojo.sql._needsEncrypt(sql) || dojo.sql._needsDecrypt(sql)){ 
     52                        callbackFunction = args.splice(args.length - 1, 1)[0]; 
     53                        password = args.splice(args.length - 1, 1)[0]; 
     54                } 
     55         
     56                // 'args' now just has the SQL parameters 
     57         
     58                // get the Gears Database object 
     59                if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
     60                        dojo.sql.db = google.gears.factory.create("beta.database", "1.0"); 
     61                } 
     62         
     63                // print out debug SQL output if the developer wants that 
     64                if(dojo.sql.debug == true){ 
     65                        dojo.sql._printDebugSQL(sql, args); 
     66                } 
     67         
     68                // handle SQL that needs encryption/decryption differently 
     69                // do we have an ENCRYPT SQL statement? if so, handle that first 
     70                if(dojo.sql._needsEncrypt(sql)){ 
     71                        dojo.sql._execEncryptSQL(sql, password, args, callbackFunction); 
     72                        return; // encrypted results will arrive asynchronously 
     73                }else if(dojo.sql._needsDecrypt(sql)){ // otherwise we have a DECRYPT statement 
     74                        dojo.sql._execDecryptSQL(sql, password, args, callbackFunction); 
     75                        return; // decrypted results will arrive asynchronously 
     76                } 
     77 
     78                // execute the SQL and get the results 
    7979                var rs = dojo.sql.db.execute(sql, args); 
    80         }catch(exp){ 
    81                 if(typeof exp.message != "undefined"){ 
    82                         throw exp.message; 
    83                 }else{ 
    84                         throw exp; 
    85                 } 
    86         } 
    87          
    88         // Gears ResultSet object's are ugly -- normalize 
    89         // these into something JavaScript programmers know 
    90         // how to work with, basically an array of  
    91         // JavaScript objects where each property name is 
    92         // simply the field name for a column of data 
    93         return dojo.sql._normalizeResults(rs); 
     80         
     81                // Gears ResultSet object's are ugly -- normalize 
     82                // these into something JavaScript programmers know 
     83                // how to work with, basically an array of  
     84                // JavaScript objects where each property name is 
     85                // simply the field name for a column of data 
     86                return dojo.sql._normalizeResults(rs); 
     87        }catch(e){ 
     88                if(typeof e.message != "undefined"){ 
     89                        throw e.message; 
     90                }else{ 
     91                        throw e; 
     92                } 
     93        } 
    9494} 
    9595 
     
    101101 
    102102dojo.sql.open = function(dbName){ 
    103         if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
    104                 dojo.sql.db = google.gears.factory.create('beta.database', '1.0'); 
    105         } 
    106          
    107         if(typeof dbName == "undefined"){ 
    108                 name = dojo.sql.dbName; 
    109         } 
    110          
    111         dojo.sql.db.open(dbName); 
     103        try{ 
     104                if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
     105                        dojo.sql.db = google.gears.factory.create('beta.database', '1.0'); 
     106                } 
     107         
     108                if(typeof dbName == "undefined"){ 
     109                        name = dojo.sql.dbName; 
     110                } 
     111         
     112                dojo.sql.db.open(dbName); 
     113        }catch(e){ 
     114                if(typeof e.message != "undefined"){ 
     115                        throw e.message; 
     116                }else{ 
     117                        throw e; 
     118                } 
     119        } 
    112120} 
    113121 
    114122dojo.sql.close = function(dbName){ 
    115         if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
    116                 dojo.sql.db = google.gears.factory.create('beta.database', '1.0'); 
    117         } 
    118          
    119         if(typeof dbName == "undefined"){ 
    120                 name = dojo.sql.dbName; 
    121         } 
    122          
    123         dojo.sql.db.close(dbName); 
     123        try{ 
     124                if(dojo.sql.db == null || typeof dojo.sql.db == "undefined"){ 
     125                        dojo.sql.db = google.gears.factory.create('beta.database', '1.0'); 
     126                } 
     127         
     128                if(typeof dbName == "undefined"){ 
     129                        name = dojo.sql.dbName; 
     130                } 
     131         
     132                dojo.sql.db.close(dbName); 
     133        }catch(e){ 
     134                if(typeof e.message != "undefined"){ 
     135                        throw e.message; 
     136                }else{ 
     137                        throw e; 
     138                } 
     139        } 
    124140} 
    125141 
  • branches/dot_experiment/src/storage/Gears.js

    r8870 r8875  
    3636                 
    3737                // create the table that holds our data 
    38                 dojo.sql.open(); 
    39                 dojo.sql("CREATE TABLE IF NOT EXISTS " + this.TABLE_NAME + "( " 
    40                                         + " namespace TEXT, " 
    41                                         + " key TEXT UNIQUE, " 
    42                                         + " value TEXT " 
    43                                         + ")" 
    44                                 ); 
    45                 dojo.sql("CREATE UNIQUE INDEX IF NOT EXISTS namespace_key_index"  
    46                                         + " ON " + this.TABLE_NAME 
    47                                         + " (namespace, key)"); 
    48                 dojo.sql.close(); 
     38                try{ 
     39                        dojo.sql.open(); 
     40                        dojo.sql("CREATE TABLE IF NOT EXISTS " + this.TABLE_NAME + "( " 
     41                                                + " namespace TEXT, " 
     42                                                + " key TEXT UNIQUE, " 
     43                                                + " value TEXT " 
     44                                                + ")" 
     45                                        ); 
     46                        dojo.sql("CREATE UNIQUE INDEX IF NOT EXISTS namespace_key_index"  
     47                                                + " ON " + this.TABLE_NAME 
     48                                                + " (namespace, key)"); 
     49                        dojo.sql.close(); 
     50                }catch(e){ 
     51                        dojo.debug("dojo.storage.Gears.initialize: " + e); 
     52                         
     53                        this.initialized = false; // we were unable to initialize 
     54                        dojo.storage.manager.loaded(); 
     55                        return; 
     56                } 
    4957                 
    5058                // indicate that this storage provider is now loaded