Skip to content
This repository
Browse code

Initial checkin of the Push Capture sample app.

  • Loading branch information...
commit 914b1aa9544f11bd82032b07125d4cc3970e0503 1 parent b63a231
Matthew D'Andrea authored

Showing 30 changed files with 15,280 additions and 0 deletions. Show diff stats Hide diff stats

  1. BIN  pushCapture/Images/actionbar/configicon.png
  2. BIN  pushCapture/Images/actionbar/deleteallicon.png
  3. BIN  pushCapture/Images/actionbar/homeicon.png
  4. BIN  pushCapture/Images/actionbar/markallicon.png
  5. BIN  pushCapture/Images/actionbar/registericon.png
  6. BIN  pushCapture/Images/actionbar/unregistericon.png
  7. BIN  pushCapture/Images/browser.png
  8. BIN  pushCapture/Images/memo.png
  9. BIN  pushCapture/Images/notify.png
  10. BIN  pushCapture/Images/pictures.png
  11. BIN  pushCapture/Images/pushCaptureIcon.png
  12. BIN  pushCapture/Images/pushCaptureSplash.png
  13. BIN  pushCapture/Images/trash.png
  14. BIN  pushCapture/Images/trashhighlight.png
  15. 56  pushCapture/README.md
  16. 5,592  pushCapture/Scripts/bbui-0.9.3.js
  17. 766  pushCapture/Scripts/common.js
  18. 326  pushCapture/Scripts/configuration.js
  19. 433  pushCapture/Scripts/pushhandler.js
  20. 647  pushCapture/Scripts/pushlist.js
  21. 410  pushCapture/Scripts/register.js
  22. 194  pushCapture/Scripts/simchangehandler.js
  23. 338  pushCapture/Scripts/unregister.js
  24. 1,368  pushCapture/Scripts/webworks-1.0.0.7.js
  25. 4,682  pushCapture/Styles/bbui-0.9.3.css
  26. 26  pushCapture/config.xml
  27. 27  pushCapture/content.htm
  28. 111  pushCapture/index.htm
  29. 101  pushCapture/pushlist.htm
  30. 203  pushCapture/userinput.htm
BIN  pushCapture/Images/actionbar/configicon.png
BIN  pushCapture/Images/actionbar/deleteallicon.png
BIN  pushCapture/Images/actionbar/homeicon.png
BIN  pushCapture/Images/actionbar/markallicon.png
BIN  pushCapture/Images/actionbar/registericon.png
BIN  pushCapture/Images/actionbar/unregistericon.png
BIN  pushCapture/Images/browser.png
BIN  pushCapture/Images/memo.png
BIN  pushCapture/Images/notify.png
BIN  pushCapture/Images/pictures.png
BIN  pushCapture/Images/pushCaptureIcon.png
BIN  pushCapture/Images/pushCaptureSplash.png
BIN  pushCapture/Images/trash.png
BIN  pushCapture/Images/trashhighlight.png
56  pushCapture/README.md
Source Rendered
... ...
@@ -0,0 +1,56 @@
  1
+# Push Capture Sample Application
  2
+
  3
+The Push Capture sample (post coming soon!) app demonstrates how to write a BlackBerry 10 WebWorks application that uses push. 
  4
+
  5
+The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html).
  6
+
  7
+
  8
+**Applies To**
  9
+
  10
+* [BlackBerry 10 WebWorks SDK](https://developer.blackberry.com/html5/download/sdk)
  11
+
  12
+**Author(s)** 
  13
+
  14
+* [Matthew D'Andrea](https://github.com/mdandrea)
  15
+* [Marco Di Cesare](https://github.com/mdicesare)
  16
+
  17
+**Dependencies**
  18
+
  19
+* bbUI.js 0.9.3 (https://github.com/blackberry/bbUI.js/tree/next)
  20
+
  21
+**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).**
  22
+
  23
+
  24
+## How to Build
  25
+
  26
+To build the Push Capture sample application:
  27
+
  28
+1. Click on the **Downloads** tab above.
  29
+2. Select **Download as zip** (Windows) or **Download as tar.gz** (Mac) and save the downloaded file to your local machine.
  30
+3. Create a new folder on your local machine named **pushCapture** e.g. **C:\Documents and Settings\User\WebWorks\pushCapture** (Windows) or **~/WebWorks/pushCapture** (Mac).
  31
+4. Open the downloaded ZIP file from step 2 and extract the contents **from inside the zipped pushCapture folder** to your local **pushCapture** folder from step 3.  This ensures that the necessary application assets, such as **config.xml**, are correctly located at the top level of the local **pushCapture** folder (e.g. **~/WebWorks/pushCapture/config.xml**).
  32
+5. When you're ready to try out the Push Capture sample app on your BlackBerry 10 device (the simulator is not yet supported), make sure you first download the **[BlackBerry 10 WebWorks SDK](https://developer.blackberry.com/html5/download/sdk)**.
  33
+6. Create a ZIP file from your local **pushCapture** folder with **config.html** and the HTML files at the **root level** of your ZIP (the root level should not be a folder).  See **[Creating a WebWorks archive file](https://developer.blackberry.com/html5/documentation/ww_developing/creating_an_archive_file_1873325_11.html)** for more details. 
  34
+7. Follow the instructions from **[Package your BlackBerry 10 app with the BlackBerry 10 WebWorks SDK](https://developer.blackberry.com/html5/documentation/ww_developing/package_your_bb10_app_with_ww_sdk_2008473_11.html)** to get the app running on your BlackBerry 10 device.
  35
+
  36
+
  37
+## More Info
  38
+
  39
+* [BlackBerry HTML5 WebWorks](https://developer.blackberry.com/html5/) - Downloads, Getting Started guides, samples, code signing keys.
  40
+* [BlackBerry WebWorks Development Guides] (https://developer.blackberry.com/html5/documentation/)
  41
+* [BlackBerry WebWorks Community Forums](http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/bd-p/browser_dev)
  42
+* [BlackBerry Open Source WebWorks Contributions Forums](http://supportforums.blackberry.com/t5/BlackBerry-WebWorks/bd-p/ww_con)
  43
+
  44
+
  45
+## Contributing Changes
  46
+
  47
+Please see the [README](https://github.com/blackberry/WebWorks-Samples) of the WebWorks-Samples repository for instructions on how to add new Samples or make modifications to existing Samples.
  48
+
  49
+
  50
+## Bug Reporting and Feature Requests
  51
+
  52
+If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/WebWorks-Samples/issues) for the Sample.
  53
+
  54
+## Disclaimer
  55
+
  56
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5,592  pushCapture/Scripts/bbui-0.9.3.js
5592 additions, 0 deletions not shown
766  pushCapture/Scripts/common.js
... ...
@@ -0,0 +1,766 @@
  1
+/*
  2
+ * Copyright 2012 Research In Motion Limited.
  3
+ *
  4
+ * Licensed under the Apache License, Version 2.0 (the "License");
  5
+ * you may not use this file except in compliance with the License.
  6
+ * You may obtain a copy of the License at
  7
+ *
  8
+ *     http://www.apache.org/licenses/LICENSE-2.0
  9
+ *
  10
+ * Unless required by applicable law or agreed to in writing, software
  11
+ * distributed under the License is distributed on an "AS IS" BASIS,
  12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13
+ * See the License for the specific language governing permissions and
  14
+ * limitations under the License.
  15
+ */
  16
+
  17
+/**
  18
+ * @fileOverview This file has common functions to be shared amongst the other JavaScript files.
  19
+ * @version 1.0
  20
+ * @name common.js
  21
+ */
  22
+
  23
+/**
  24
+ * @namespace
  25
+ * @description The namespace for the Push Capture application.
  26
+ */
  27
+
  28
+window.sample = {};
  29
+
  30
+sample.pushcapture = (function() {
  31
+
  32
+    /**
  33
+     * Constructs a Push Capture object.
  34
+     * 
  35
+     * @constructor
  36
+     */
  37
+    function PushCapture() {
  38
+        /**
  39
+         * Returns a string with leading and trailing whitespace removed.
  40
+         * 
  41
+         * @returns {String} a string with leading and trailing whitespace removed
  42
+         * @memberOf String
  43
+         */
  44
+        String.prototype.trim = function() {
  45
+            return (this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""));
  46
+        };
  47
+
  48
+        /**
  49
+         * Returns true if a string starts with the specified prefix.
  50
+         * 
  51
+         * @param {String}
  52
+         *            str the prefix
  53
+         * @returns {Boolean} true if a string starts with the specified prefix
  54
+         * @memberOf String
  55
+         */
  56
+        String.prototype.startsWith = function(str) {
  57
+            return (this.match("^" + str) == str);
  58
+        };
  59
+
  60
+        /**
  61
+         * Returns true if a string ends with the specified suffix.
  62
+         * 
  63
+         * @param {String}
  64
+         *            str the suffix
  65
+         * @returns {Boolean} true if a string ends with the specified suffix
  66
+         * @memberOf String
  67
+         */
  68
+        String.prototype.endsWith = function(str) {
  69
+            return (this.match(str + "$") == str);
  70
+        };
  71
+
  72
+        /**
  73
+         * The database to store pushes, configuration, registration, etc. in.
  74
+         * 
  75
+         * @constant
  76
+         */
  77
+        this.db;
  78
+        try {
  79
+            this.db = openDatabase("pushcapture", "1.0", "Push capture storage", 5 * 1024 * 1024);
  80
+        } catch (err) {
  81
+            // Do nothing here since the db will be left uninitialized and the proper error will be
  82
+            // displayed when the user attempts to perform an operation that requires a db transaction
  83
+        }
  84
+
  85
+        /**
  86
+         * The cookie to store the list of pushes to make it quicker to display when possible.
  87
+         * 
  88
+         * @constant
  89
+         */
  90
+        this.cookieName = "pushlistcookie";
  91
+
  92
+        /**
  93
+         * The error message received when attempting to use the application and a database error
  94
+         * is encountered.
  95
+         * 
  96
+         * @constant
  97
+         */
  98
+        this.databaseError = "Error: Problem was encountered while attempting to access the database.";
  99
+        
  100
+        /**
  101
+         * The message to be displayed when no pushes exist in the database.
  102
+         * 
  103
+         * @constant
  104
+         */
  105
+        this.noPushesMessage = "There are currently no pushes.";
  106
+        
  107
+        /**
  108
+         * PushService object obtained from a success call to blackberry.push.PushService.create.
  109
+         */
  110
+        this.pushService = null;
  111
+        
  112
+        /**
  113
+         * Invoke target ID for receiving new push notifications.
  114
+         */
  115
+        this.invoketargetid = "net.rim.pushcapture.target";
  116
+        
  117
+        /**
  118
+         * Use SDK as Push Initiator configuration setting.
  119
+         * This indicates whether or not the Push Service SDK will be used to manage
  120
+         * subscriptions for the Push Initiator.
  121
+         */
  122
+        this.usesdkaspi = true;
  123
+        
  124
+        /**
  125
+         * Whether the public/BIS PPG is being used.  If set to false, an
  126
+         * enterprise/BES PPG is being used.
  127
+         */
  128
+        this.usingpublicppg = true;
  129
+        
  130
+        /**
  131
+         * Launch Application on a New Push configuration setting.
  132
+         * This indicates whether or not the application should be launched/started up
  133
+         * if it is closed and a new push comes in.
  134
+         */
  135
+        this.launchapp = false;
  136
+        
  137
+        /**
  138
+         * Application ID configuration setting.
  139
+         */
  140
+        this.appid = null;
  141
+
  142
+        /**
  143
+         * Push Initiator URL configuration setting.
  144
+         */
  145
+        this.piurl = null;
  146
+
  147
+        /**
  148
+         * PPG URL configuration setting.
  149
+         */
  150
+        this.ppgurl = null;
  151
+
  152
+        /**
  153
+         * Username registration information.
  154
+         */
  155
+        this.userid = null;
  156
+
  157
+        /**
  158
+         * Password registration information.
  159
+         */
  160
+        this.passwd = null;
  161
+        
  162
+        /**
  163
+         * The push that is currently selected.
  164
+         */
  165
+        this.selectedPushSeqnum = null;
  166
+        
  167
+        /**
  168
+         * The push content to be displayed.
  169
+         */     
  170
+        this.content = null;
  171
+
  172
+        /**
  173
+         * Keep a count of the number of calls that were attempted to 
  174
+         * <code>sample.pushcapture.onInvoke</code> and no <code>PushService</code>   
  175
+         * instance was found.
  176
+         */
  177
+        this.onInvokeAttemptCount = 0;
  178
+        
  179
+        /**
  180
+         * Keep a count of the number of unregister attempts with the Push Initiator.
  181
+         */
  182
+        this.unregisterAttemptCount = 0;
  183
+    }
  184
+
  185
+    /**
  186
+     * Converts a Blob to a text string with the given encoding.
  187
+     * 
  188
+     * @param {Blob}
  189
+     *            blob the blob to be converted
  190
+     * @param {String}
  191
+     *            encoding the encoding of the Blob
  192
+     * @param {function}
  193
+     *            callback the callback to be called with the string result         
  194
+     * @memberOf sample.pushcapture
  195
+     */
  196
+    PushCapture.prototype.blobToTextString = function(blob, encoding, callback) {
  197
+    	var reader = new FileReader();
  198
+    	
  199
+    	reader.onload = function(evt) {
  200
+        	// No errors, get the result and call the callback
  201
+        	callback(evt.target.result);
  202
+    	};
  203
+    	
  204
+    	reader.onerror = function(evt) {
  205
+        	console.log("Error converting Blob to string: " + evt.target.error);
  206
+    	};
  207
+        
  208
+        reader.readAsText(blob, encoding);
  209
+    };
  210
+    
  211
+    /**
  212
+     * Converts a Blob to a binary base64 encoded string.
  213
+     * 
  214
+     * @param {Blob}
  215
+     *            blob the blob to be converted
  216
+     * @param {function}
  217
+     *            callback the callback to be called with the binary base64 encoded string         
  218
+     * @memberOf sample.pushcapture
  219
+     */
  220
+    PushCapture.prototype.blobToBinaryBase64String = function(blob, callback) {
  221
+    	var reader = new FileReader();
  222
+    	
  223
+    	reader.onload = function(evt) {
  224
+        	// No errors, base64 encode the result and call the callback
  225
+        	callback(sample.pushcapture.arrayBufferToBase64(evt.target.result));
  226
+    	};
  227
+    	
  228
+    	reader.onerror = function(evt) {
  229
+        	console.log("Error converting Blob to binary base64 string: " + evt.target.error);
  230
+    	};
  231
+        
  232
+        reader.readAsArrayBuffer(blob);
  233
+    };
  234
+    
  235
+    /**
  236
+     * Converts an ArrayBuffer to a base64 encoded string.
  237
+     * 
  238
+     * @param {ArrayBuffer}
  239
+     *            arrayBuffer the ArrayBuffer to be converted       
  240
+     * @memberOf sample.pushcapture
  241
+     */
  242
+    PushCapture.prototype.arrayBufferToBase64 = function(arrayBuffer) {
  243
+        var binary = "";
  244
+        var bytes = new Uint8Array(arrayBuffer);
  245
+        var len = bytes.byteLength;
  246
+        
  247
+        for (var i = 0; i < len; i++) {
  248
+            binary += String.fromCharCode(bytes[i]);
  249
+        }
  250
+            
  251
+        return window.btoa(binary);
  252
+    };       
  253
+    
  254
+    /**
  255
+     * Returns the English abbreviation for a month.
  256
+     * 
  257
+     * @param {Number}
  258
+     *            month a month of the year (from 0-11)
  259
+     * @returns {String} a month's English abbreviation
  260
+     * @memberOf sample.pushcapture
  261
+     */
  262
+    PushCapture.prototype.getMonthText = function(month) {
  263
+        if (month == 0) {
  264
+            return "Jan";
  265
+        } else if (month == 1) {
  266
+            return "Feb";
  267
+        } else if (month == 2) {
  268
+            return "Mar";
  269
+        } else if (month == 3) {
  270
+            return "Apr";
  271
+        } else if (month == 4) {
  272
+            return "May";
  273
+        } else if (month == 5) {
  274
+            return "Jun";
  275
+        } else if (month == 6) {
  276
+            return "Jul";
  277
+        } else if (month == 7) {
  278
+            return "Aug";
  279
+        } else if (month == 8) {
  280
+            return "Sep";
  281
+        } else if (month == 9) {
  282
+            return "Oct";
  283
+        } else if (month == 10) {
  284
+            return "Nov";
  285
+        } else {
  286
+            return "Dec";
  287
+        }
  288
+    };
  289
+
  290
+    /**
  291
+     * Returns the English abbreviation for a day of the week.
  292
+     * 
  293
+     * @param {Number}
  294
+     *            day a day of the week (from 0-6)
  295
+     * @returns {String} a day of the week's English abbreviation
  296
+     * @memberOf sample.pushcapture
  297
+     */
  298
+    PushCapture.prototype.getDayOfWeekText = function(day) {
  299
+        if (day == 0) {
  300
+            return "Sun";
  301
+        } else if (day == 1) {
  302
+            return "Mon";
  303
+        } else if (day == 2) {
  304
+            return "Tue";
  305
+        } else if (day == 3) {
  306
+            return "Wed";
  307
+        } else if (day == 4) {
  308
+            return "Thu";
  309
+        } else if (day == 5) {
  310
+            return "Fri";
  311
+        } else if (day == 6) {
  312
+            return "Sat";
  313
+        }
  314
+    };
  315
+
  316
+    /**
  317
+     * Returns the path to an icon based on the type passed in.
  318
+     * 
  319
+     * @param {String}
  320
+     *            type the content type
  321
+     * @returns {String} an image path
  322
+     * @memberOf sample.pushcapture
  323
+     */
  324
+    PushCapture.prototype.getIconForType = function(type) {
  325
+        if (type == "image") {
  326
+            return "Images/pictures.png";
  327
+        } else if (type == "xml") {
  328
+            return "Images/browser.png";
  329
+        } else {
  330
+            return "Images/memo.png";
  331
+        }
  332
+    };
  333
+
  334
+    /**
  335
+     * Returns a preview of the content based on the type passed in.
  336
+     * 
  337
+     * @param {String}
  338
+     *            type the content type
  339
+     * @param {String}
  340
+     *            extension the file extension of the push content      
  341
+     * @param {String}
  342
+     *            content the content to be previewed (a base64 encoded string)
  343
+     * @returns {String} a preview of the content
  344
+     * @memberOf sample.pushcapture
  345
+     */
  346
+    PushCapture.prototype.getPushPreview = function(type, extension, content) {
  347
+        if (type == "image") {
  348
+            return "Image: " + extension;
  349
+        } else if (type == "xml") {
  350
+            if (extension == ".html") {
  351
+                return "HTML/XML: .html";
  352
+            } else {
  353
+                return "HTML/XML: .xml";
  354
+            }
  355
+        } else {
  356
+            // Base 64 decode the string
  357
+        	var textStr = window.atob(content);
  358
+        	
  359
+            // We want to limit the previewed content to 25 characters (including the "..." part)
  360
+            var part = textStr.substring(0, 22);
  361
+            
  362
+            if (textStr != part) {
  363
+                part += "...";
  364
+            }
  365
+
  366
+            return part;
  367
+        }
  368
+    };
  369
+    
  370
+    /**
  371
+     * Shows the user input screen.
  372
+     * 
  373
+     * @param {String}
  374
+     *            tabId the id of the tab to show
  375
+     * @memberOf sample.pushcapture
  376
+     */
  377
+    PushCapture.prototype.showUserInputScreen = function(tabId) {
  378
+    	bb.pushScreen('userinput.htm', tabId);
  379
+    };
  380
+   
  381
+    /**
  382
+     * Shows the config tab.
  383
+     * 
  384
+     * @memberOf sample.pushcapture
  385
+     */
  386
+    PushCapture.prototype.showConfigTab = function() {
  387
+    	// Only do something if we are not already on the config tab
  388
+    	if (document.getElementById("config-tab").style.display == "none") {    		
  389
+	    	// Updates the title bar
  390
+	    	document.getElementById("user-input-title").setCaption("Configuration");
  391
+	    	document.getElementById("user-input-title").setActionCaption("Save");
  392
+	    	document.getElementById("user-input-title").onactionclick = function() { sample.pushcapture.configure(); };
  393
+			
  394
+	    	// Shows the config tab, hides the others
  395
+	    	document.getElementById("errordiv").style.display = "none";
  396
+	    	document.getElementById("progressinfo").style.display = "none";
  397
+	        document.getElementById("register-tab").style.display = "none";
  398
+	        document.getElementById("unregister-tab").style.display = "none";
  399
+	        document.getElementById("config-tab").style.display = "block";
  400
+	        
  401
+	    	sample.pushcapture.initConfiguration(document);
  402
+    	} 
  403
+    };
  404
+    
  405
+    /**
  406
+     * Shows the register tab.
  407
+     * 
  408
+     * @memberOf sample.pushcapture
  409
+     */
  410
+    PushCapture.prototype.showRegisterTab = function() {
  411
+    	// Only do something if we are not already on the register tab
  412
+    	if (document.getElementById("register-tab").style.display == "none") {
  413
+	    	// Updates the title bar
  414
+	    	document.getElementById("user-input-title").setCaption("Register");
  415
+		    document.getElementById("user-input-title").setActionCaption("Submit");
  416
+	    	document.getElementById("user-input-title").onactionclick = function() { sample.pushcapture.register(); };
  417
+	    	
  418
+	    	// Shows the register tab, hides the others
  419
+	    	document.getElementById("errordiv").style.display = "none";
  420
+	    	document.getElementById("progressinfo").style.display = "none";
  421
+	        document.getElementById("config-tab").style.display = "none";
  422
+	        document.getElementById("unregister-tab").style.display = "none";
  423
+	        document.getElementById("register-tab").style.display = "block";
  424
+	       
  425
+	        sample.pushcapture.initRegister(document);
  426
+			
  427
+			sample.pushcapture.checkIfConfigExists();
  428
+    	}
  429
+    };
  430
+
  431
+    /**
  432
+     * Shows the unregister tab.
  433
+     * 
  434
+     * @memberOf sample.pushcapture
  435
+     */
  436
+    PushCapture.prototype.showUnregisterTab = function() {
  437
+    	// Only do something if we are not already on the unregister tab
  438
+    	if (document.getElementById("unregister-tab").style.display == "none") {
  439
+	    	// Updates the title bar
  440
+	    	document.getElementById("user-input-title").setCaption("Unregister");
  441
+	    	document.getElementById("user-input-title").setActionCaption("Submit");
  442
+	    	document.getElementById("user-input-title").onactionclick = function() { sample.pushcapture.unregister(); };
  443
+			
  444
+	    	// Shows the unregister tab, hides the others
  445
+	    	document.getElementById("errordiv").style.display = "none";
  446
+	    	document.getElementById("progressinfo").style.display = "none";
  447
+	        document.getElementById("config-tab").style.display = "none";
  448
+	        document.getElementById("register-tab").style.display = "none";
  449
+	        document.getElementById("unregister-tab").style.display = "block";
  450
+	        
  451
+	        sample.pushcapture.initUnregister(document);
  452
+			
  453
+			sample.pushcapture.checkIfConfigExists();
  454
+    	}
  455
+    };
  456
+    
  457
+    /**
  458
+     * Checks if configuration settings are found in the database and displays an error if there are not any.
  459
+     * 
  460
+     * @memberOf sample.pushcapture
  461
+     */
  462
+    PushCapture.prototype.checkIfConfigExists = function() {        
  463
+        try {
  464
+            sample.pushcapture.db.readTransaction(function(tx) {
  465
+                tx.executeSql("SELECT appid, piurl, ppgurl, usesdkaspi, usingpublicppg, launchapp FROM configuration;", [], null,
  466
+                        sample.pushcapture.displayNoConfigError);
  467
+            });
  468
+        } catch (e) {
  469
+            alert(sample.pushcapture.databaseError);
  470
+        }
  471
+    };
  472
+
  473
+    /**
  474
+     * Initializes the push service. 
  475
+     * <br/> 
  476
+     * NOTE: This must be called every time a new page loads up.
  477
+     * 
  478
+     * @memberOf sample.pushcapture
  479
+     */
  480
+    PushCapture.prototype.initPushService = function() {    	
  481
+		// Add an event listener to handle incoming push notifications
  482
+		// We will ignore non-push invoke events
  483
+    	blackberry.event.addEventListener("invoked", sample.pushcapture.onInvoke);
  484
+    	
  485
+        try {
  486
+            sample.pushcapture.db.readTransaction(function(tx) {
  487
+                tx.executeSql("SELECT appid, piurl, ppgurl, usesdkaspi, usingpublicppg, launchapp FROM configuration;", [],
  488
+                        sample.pushcapture.loadRegistration);
  489
+            });
  490
+        } catch (e) {
  491
+            alert(sample.pushcapture.databaseError);
  492
+        }
  493
+    };
  494
+    
  495
+    /**
  496
+     * Handles an incoming invoke request.  Note that non-push invokes are ignored.
  497
+     * Push invokes will have the <code>PushPayload</code> extracted and be passed off to 
  498
+     * <code>sample.pushcapture.pushNotificationHandler</code> for processing.
  499
+     * 
  500
+     * @param {JSON}
  501
+     *            invokeRequest an invoke request
  502
+     * @memberOf sample.pushcapture
  503
+     */
  504
+    PushCapture.prototype.onInvoke = function(invokeRequest) {    	
  505
+    	if (invokeRequest.action != null && invokeRequest.action == "bb.action.PUSH") {
  506
+    		if (sample.pushcapture.onInvokeAttemptCount < 10 && sample.pushcapture.pushService == null) {    			
  507
+    			// Wait a bit for the PushService instance to be created and then try again
  508
+    			setTimeout(function() { sample.pushcapture.onInvoke(invokeRequest); }, 500);
  509
+    		} else if (sample.pushcapture.pushService != null) {    			
  510
+            	var pushPayload = sample.pushcapture.pushService.extractPushPayload(invokeRequest);            	
  511
+            	sample.pushcapture.pushNotificationHandler(pushPayload);
  512
+    		} else {
  513
+    			console.log("Error: No PushService instance was available to extract the push.");
  514
+    		}
  515
+    	}
  516
+    };
  517
+    
  518
+    /**
  519
+     * Loads the stored registration information (i.e. user id and password) and then tries to
  520
+     * create a <code>blackberry.push.PushService</code> object with a call to <code>createPushService</code>.
  521
+     * 
  522
+     * @param {SQLTransaction}
  523
+     *            tx a database transaction
  524
+     * @param {SQLResultSet}
  525
+     *            results the results of the query executed in the initPushService() function
  526
+     * @memberOf sample.pushcapture
  527
+     */
  528
+    PushCapture.prototype.loadRegistration = function(tx, results) {
  529
+        sample.pushcapture.appid = results.rows.item(0).appid;
  530
+        sample.pushcapture.piurl = results.rows.item(0).piurl;
  531
+        sample.pushcapture.ppgurl = results.rows.item(0).ppgurl;
  532
+        if (results.rows.item(0).usingpublicppg == 1) {
  533
+        	sample.pushcapture.usingpublicppg = true;
  534
+        } else {
  535
+        	sample.pushcapture.usingpublicppg = false;
  536
+        }
  537
+        if (results.rows.item(0).launchapp == 1) {
  538
+        	sample.pushcapture.launchapp = true;
  539
+        } else {
  540
+        	sample.pushcapture.launchapp = false;
  541
+        }
  542
+        if (results.rows.item(0).usesdkaspi == 1) {
  543
+        	sample.pushcapture.usesdkaspi = true;
  544
+        } else {
  545
+        	sample.pushcapture.usesdkaspi = false;
  546
+        }        
  547
+        
  548
+        sample.pushcapture.db.readTransaction(function(tx) {
  549
+            tx.executeSql("SELECT userid, passwd FROM registration;", [],
  550
+                function(tx, results) {
  551
+                    sample.pushcapture.userid = results.rows.item(0).userid;
  552
+                    sample.pushcapture.passwd = results.rows.item(0).passwd;
  553
+                
  554
+                    sample.pushcapture.createPushService();
  555
+                }, function(tx, e) {
  556
+                    sample.pushcapture.createPushService();
  557
+                });
  558
+        });
  559
+    };
  560
+
  561
+    /**
  562
+     * Attempts to create a <code>blackberry.push.PushService</code> object to
  563
+     * be used for performing push-related operations such as createChannel, etc.
  564
+	 *
  565
+     * @memberOf sample.pushcapture
  566
+     */
  567
+    PushCapture.prototype.createPushService = function() {    	
  568
+    	var ops;
  569
+    	if (sample.pushcapture.usingpublicppg) {
  570
+    		// Consumer application using public push
  571
+    		ops = { invokeTargetId : sample.pushcapture.invoketargetid, 
  572
+    				appId : sample.pushcapture.appid, 
  573
+    				ppgUrl : sample.pushcapture.ppgurl 
  574
+    			  };
  575
+    	} else {
  576
+    	    // Enterprise application using enterprise push
  577
+    		if (sample.pushcapture.usesdkaspi) {
  578
+    			// If we're using the Push Service SDK for our Push Initiator 
  579
+    			// implementation, we will have specified our own application ID to use
  580
+        		ops = { invokeTargetId : sample.pushcapture.invoketargetid, 
  581
+        				appId : sample.pushcapture.appid
  582
+        			  };
  583
+    		} else {
  584
+    			ops = { invokeTargetId : sample.pushcapture.invoketargetid };
  585
+    		}
  586
+    	}
  587
+    	
  588
+    	blackberry.push.PushService.create(ops, sample.pushcapture.successCreatePushService, 
  589
+    			sample.pushcapture.failCreatePushService, sample.pushcapture.onSimChange);
  590
+    };
  591
+    
  592
+    /**
  593
+     * After successfully creating a <code>blackberry.push.PushService</code> object,
  594
+     * we store it to a global variable so that it can be used across pages.
  595
+     * A call will also be made to set the application to launch on a new push if the 
  596
+     * (configuration settings checkbox had been checked).  If the checkbox had been 
  597
+     * unchecked, we will tell the application not to launch on a new push.
  598
+     * 
  599
+     * @param {blackberry.push.PushService}
  600
+     *            service a <code>blackberry.push.PushService</code> object
  601
+     * @memberOf sample.pushcapture
  602
+     */
  603
+    PushCapture.prototype.successCreatePushService = function(service) {    	
  604
+    	// Save the service into a global variable so that it can be used later for operations
  605
+        // such as create channel, destroy channel, etc.
  606
+    	sample.pushcapture.pushService = service;
  607
+    	
  608
+    	// We'll use the PushService object right now in fact to indicate whether we want to
  609
+    	// launch the application on a new push or not
  610
+    	sample.pushcapture.pushService.launchApplicationOnPush(sample.pushcapture.launchapp, 
  611
+    			sample.pushcapture.launchApplicationCallback);
  612
+    };
  613
+    
  614
+    /**
  615
+     * After failing to create a <code>blackberry.push.PushService</code> object,
  616
+     * respond to the possible errors.
  617
+     * 
  618
+     * @param {Number}
  619
+     *            result an error code
  620
+     * @memberOf sample.pushcapture
  621
+     */
  622
+    PushCapture.prototype.failCreatePushService = function(result) {
  623
+		if (document.getElementById("config-table") != null) {
  624
+			// On the configuration screen
  625
+			document.body.removeChild(document.getElementById("op-in-progress"));
  626
+			document.getElementById("activityindicator").style.display = "none";
  627
+			document.getElementById("progressinfo").style.display = "none";
  628
+		}
  629
+    	
  630
+    	if (result == blackberry.push.PushService.INTERNAL_ERROR) {
  631
+			alert("Error: An internal error occurred while calling " +
  632
+			"blackberry.push.PushService.create. Try restarting the application.");
  633
+    	} else if (result == blackberry.push.PushService.INVALID_PROVIDER_APPLICATION_ID) {
  634
+    		// This error only applies to consumer applications that use a public/BIS PPG
  635
+			alert("Error: Called blackberry.push.PushService.create with a missing " +
  636
+			"or invalid appId value. It usually means a programming error.");
  637
+    	} else if (result == blackberry.push.PushService.MISSING_INVOKE_TARGET_ID) {
  638
+			alert("Error: Called blackberry.push.PushService.create with a missing " +
  639
+			"invokeTargetId value. It usually means a programming error.");
  640
+    	} else {
  641
+			alert("Error: Received error code (" + result + ") after " +
  642
+			"calling blackberry.push.PushService.create.");
  643
+    	}
  644
+    };
  645
+    
  646
+    /**
  647
+     * This is the callback after calling the <code>launchApplicationOnPush</code> function on a
  648
+     * <code>blackberry.push.PushService</code> object. The call may or may not have been successful.
  649
+     * Handle possible errors accordingly.
  650
+     * 
  651
+     * @param {Number}
  652
+     *            result either a success code or an error code
  653
+     * @memberOf sample.pushcapture
  654
+     */
  655
+    PushCapture.prototype.launchApplicationCallback = function(result) {    	
  656
+    	if (result == blackberry.push.PushService.SUCCESS) {
  657
+    		if (document.getElementById("config-table") != null) {
  658
+    			// On the configuration screen
  659
+    			sample.pushcapture.successfulConfiguration();
  660
+    		}
  661
+    	} else {    		
  662
+    		if (document.getElementById("config-table") != null) {
  663
+    			// On the configuration screen
  664
+    			document.body.removeChild(document.getElementById("op-in-progress"));
  665
+    			document.getElementById("activityindicator").style.display = "none";
  666
+    			document.getElementById("progressinfo").style.display = "none";
  667
+    		}
  668
+    		
  669
+	    	if (result == blackberry.push.PushService.INTERNAL_ERROR) {
  670
+				alert("Error: An internal error occurred while calling launchApplicationOnPush. " +
  671
+				"Try restarting the application.");
  672
+	    	} else if (result == blackberry.push.PushService.CREATE_SESSION_NOT_DONE) {
  673
+				alert("Error: Called launchApplicationOnPush without an " +
  674
+				"existing session. It usually means a programming error.");
  675
+	    	} else {
  676
+				alert("Error: Received error code (" + result + ") after " +
  677
+				"calling launchApplicationOnPush."); 		
  678
+	    	}
  679
+    	}
  680
+    };
  681
+    
  682
+    /**
  683
+     * Displays an error if no configuration settings are found in the database and 
  684
+     * shows the configuration tab.
  685
+     * 
  686
+     * @memberOf sample.pushcapture
  687
+     */
  688
+    PushCapture.prototype.displayNoConfigError = function() {
  689
+        alert("Error: No configuration settings were found. Please fill them in.");
  690
+
  691
+        // Show the configuration tab
  692
+    	// Check if we are already on the user input screen
  693
+        if (document.getElementById("user-input-screen") != null) {
  694
+        	// Highlight the config tab in the action bar
  695
+        	var tab = document.getElementById("user-input-config-action");
  696
+        	bb.actionBar.highlightAction(tab);
  697
+
  698
+        	sample.pushcapture.showConfigTab();
  699
+        } else {
  700
+            sample.pushcapture.showUserInputScreen("configuration");	
  701
+        }
  702
+    };
  703
+
  704
+    /**
  705
+     * Creates a cookie for storing and retrieving certain info quickly.
  706
+     * 
  707
+     * @param name
  708
+     *            the name of the cookie
  709
+     * @param value
  710
+     *            the value of the cookie
  711
+     * @param days
  712
+     *            the number of days to store the cookie for
  713
+     * @memberOf sample.pushcapture
  714
+     */
  715
+    PushCapture.prototype.createCookie = function(name, value, days) {
  716
+        var expires = "";
  717
+        
  718
+        if (days) {
  719
+            var date = new Date();
  720
+            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
  721
+            expires = "; expires=" + date.toGMTString();
  722
+        } 
  723
+
  724
+        document.cookie = name + "=" + value + expires + "; path=/";
  725
+    };
  726
+
  727
+    /**
  728
+     * Returns a cookie with the specified name.
  729
+     * 
  730
+     * @param name
  731
+     *            the name of the cookie
  732
+     * @returns the value of the cookie
  733
+     * @memberOf sample.pushcapture
  734
+     */
  735
+    PushCapture.prototype.readCookie = function(name) {
  736
+        var nameEQ = name + "=";
  737
+        var ca = document.cookie.split(';');
  738
+
  739
+        for ( var i = 0; i < ca.length; i++) {
  740
+            var c = ca[i];
  741
+
  742
+            while (c.charAt(0) == ' ') {
  743
+                c = c.substring(1, c.length);
  744
+            }
  745
+
  746
+            if (c.indexOf(nameEQ) == 0) {
  747
+                return c.substring(nameEQ.length, c.length);
  748
+            }
  749
+        }
  750
+
  751
+        return null;
  752
+    };
  753
+
  754
+    /**
  755
+     * Removes the cookie with the specified name.
  756
+     * 
  757
+     * @param name
  758
+     *            the name of the cookie
  759
+     * @memberOf sample.pushcapture
  760
+     */
  761
+    PushCapture.prototype.eraseCookie = function(name) {
  762
+        sample.pushcapture.createCookie(name, "", -1);
  763
+    };
  764
+
  765
+    return new PushCapture();
  766
+}());
326  pushCapture/Scripts/configuration.js
... ...
@@ -0,0 +1,326 @@
  1
+/*
  2
+ * Copyright 2012 Research In Motion Limited.
  3
+ *
  4
+ * Licensed under the Apache License, Version 2.0 (the "License");
  5
+ * you may not use this file except in compliance with the License.
  6
+ * You may obtain a copy of the License at
  7
+ *
  8
+ *     http://www.apache.org/licenses/LICENSE-2.0
  9
+ *
  10
+ * Unless required by applicable law or agreed to in writing, software
  11
+ * distributed under the License is distributed on an "AS IS" BASIS,
  12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13
+ * See the License for the specific language governing permissions and
  14
+ * limitations under the License.
  15
+ */
  16
+
  17
+/**
  18
+ * @fileOverview This file has functions related to the configuration settings needed for push.
  19
+ * @version 1.0
  20
+ * @name configuration.js
  21
+ */
  22
+
  23
+/**
  24
+ * When the selected PPG type is "Public/BIS", displays the "Application ID" and "PPG URL" text boxes.
  25
+ * 
  26
+ * @memberOf sample.pushcapture
  27
+ */
  28
+sample.pushcapture.constructor.prototype.publicPPG = function() {
  29
+	// Show both the PPG URL and App ID fields
  30
+    document.getElementById("ppgurl").style.display = "";
  31
+    document.getElementById("appid").style.display = "";
  32
+};
  33
+
  34
+/**
  35
+ * When the selected PPG type is "Enterprise/BES", hides the "PPG URL" text box
  36
+ * (and possibly the "Application ID" text box if not using the Push Service SDK
  37
+ * for your Push Initiator).
  38
+ * 
  39
+ * @memberOf sample.pushcapture
  40
+ */
  41
+sample.pushcapture.constructor.prototype.enterprisePPG = function() {	
  42
+	// Hide the PPG URL field
  43
+    document.getElementById("ppgurl").style.display = "none";
  44
+    
  45
+    // Show the App ID field only if the Push Service SDK will be used
  46
+    if (document.getElementById("usesdkaspi").checked) {
  47
+    	document.getElementById("appid").style.display = "";
  48
+    } else {
  49
+    	document.getElementById("appid").style.display = "none";
  50
+    }
  51
+};
  52
+
  53
+/**
  54
+ * Indicates we are using the Push Service SDK in our Push Initiator (server-side
  55
+ * push application) implementation.
  56
+ * If using the SDK, we will need to subscribe to the Push Initiator.
  57
+ * Therefore, we will display the "Push Initiator URL" text box and the 
  58
+ * "Application ID" text box.
  59
+ * 
  60
+ * @memberOf sample.pushcapture
  61
+ */
  62
+sample.pushcapture.constructor.prototype.useSDKAsPushInitiator = function() {
  63
+	if (document.getElementById("usesdkaspi").checked) {
  64
+		document.getElementById("piurl").style.display = "";
  65
+		document.getElementById("appid").style.display = "";
  66
+	} else {
  67
+		document.getElementById("piurl").style.display = "none";
  68
+		
  69
+		if (document.getElementById("publicradio").checked) {
  70
+			document.getElementById("appid").style.display = "";
  71
+		} else {
  72
+			document.getElementById("appid").style.display = "none";
  73
+		}
  74
+	}
  75
+};
  76
+
  77
+/**
  78
+ * Initializes the configuration screen's fields.
  79
+ * 
  80
+ * @param {Element}
  81
+ *            element the root element of the screen
  82
+ * @memberOf sample.pushcapture
  83
+ */
  84
+sample.pushcapture.constructor.prototype.initConfiguration = function(element) {
  85
+    try {
  86
+        sample.pushcapture.db.readTransaction(function(tx) {
  87
+            tx.executeSql("SELECT appid, piurl, ppgurl, usesdkaspi, usingpublicppg, launchapp FROM configuration;", 
  88
+                [], 
  89
+            	function(tx, results) {
  90
+            	    sample.pushcapture.displayConfig(element, tx, results);
  91
+            	    
  92
+            	    if (element.getElementById("appid") != null && element.getElementById("appid").style.display == "") {
  93
+            	        element.getElementById("appid").focus();
  94
+            	    } else if (element.getElementById("ppgurl").style.display == "") {
  95
+            	    	element.getElementById("ppgurl").focus();
  96
+            	    } else if (element.getElementById("piurl").style.display == "") {
  97
+            	    	element.getElementById("piurl").focus();
  98
+            	    }
  99
+                }
  100
+            );
  101
+        });
  102
+    } catch (e) {
  103
+        alert(sample.pushcapture.databaseError);
  104
+    }
  105
+};
  106
+
  107
+/**
  108
+ * Sets the values of the configuration fields based on the loaded configuration.
  109
+ * 
  110
+ * @param {Element}
  111
+ *            element the root element of the screen
  112
+ * @param {SQLTransaction}
  113
+ *            tx a database transaction
  114
+ * @param {SQLResultSet}
  115
+ *            results the results of the query executed in the initConfiguration() function
  116
+ * @memberOf sample.pushcapture
  117
+ */
  118
+sample.pushcapture.constructor.prototype.displayConfig = function(element, tx, results) {
  119
+	element.getElementById("appidtd").innerHTML = results.rows.item(0).appid;
  120
+	sample.pushcapture.appid = results.rows.item(0).appid;
  121
+	element.getElementById("piurl").value = results.rows.item(0).piurl;
  122
+	element.getElementById("ppgurl").value = results.rows.item(0).ppgurl;
  123
+    
  124
+    if (results.rows.item(0).usingpublicppg == 1) {
  125
+    	sample.pushcapture.usingpublicppg = true;
  126
+        element.getElementById("ppgtyperow").innerHTML = "<td class='user-input-padding'>Public/BIS</td>";
  127
+        element.getElementById("ppgurl").style.display = "";
  128
+    } else {
  129
+    	sample.pushcapture.usingpublicppg = false;
  130
+    	element.getElementById("ppgtyperow").innerHTML = "<td class='user-input-padding'>Enterprise/BES</td>";
  131
+        element.getElementById("ppgurl").style.display = "none";
  132
+    }
  133
+
  134
+    if (results.rows.item(0).launchapp == 1) {
  135
+    	element.getElementById("launchapp").setChecked(true);
  136
+    } else {
  137
+    	element.getElementById("launchapp").setChecked(false);
  138
+    }
  139
+    
  140
+    if (results.rows.item(0).usesdkaspi == 1) {
  141
+    	element.getElementById("usesdkaspi").setChecked(true);
  142
+    	element.getElementById("piurl").style.display = "";
  143
+    } else {
  144
+    	element.getElementById("usesdkaspi").setChecked(false);
  145
+    	element.getElementById("piurl").style.display = "none";
  146
+    }
  147
+};
  148
+
  149
+/**
  150
+ * Validates and, if successful, stores the entered configuration settings.
  151
+ * 
  152
+ * @memberOf sample.pushcapture
  153
+ */
  154
+sample.pushcapture.constructor.prototype.configure = function() {	
  155
+    var wasValidationSuccessful = sample.pushcapture.validateConfigFields();
  156
+
  157
+    if (wasValidationSuccessful) {
  158
+        sample.pushcapture.storeConfiguration();
  159
+    }
  160
+};
  161
+
  162
+/**
  163
+ * Validates the entered configuration settings.
  164
+ * 
  165
+ * @returns {Boolean} true if validation passes; false, otherwise
  166
+ * @memberOf sample.pushcapture
  167
+ */
  168
+sample.pushcapture.constructor.prototype.validateConfigFields = function() {
  169
+	if (document.getElementById("publicradio") != null) {
  170
+		if (document.getElementById("publicradio").checked) {
  171
+			sample.pushcapture.usingpublicppg = true;
  172
+		} else {
  173
+			sample.pushcapture.usingpublicppg = false;	
  174
+		}
  175
+	} 
  176
+	if (document.getElementById("appid") != null) {
  177
+	    sample.pushcapture.appid = document.getElementById("appid").value.trim();
  178
+	}
  179
+	sample.pushcapture.usesdkaspi = document.getElementById("usesdkaspi").checked;
  180
+	sample.pushcapture.launchapp = document.getElementById("launchapp").checked;
  181
+    sample.pushcapture.piurl = document.getElementById("piurl").value.trim();
  182
+    sample.pushcapture.ppgurl = document.getElementById("ppgurl").value.trim();
  183
+	
  184
+    if ((sample.pushcapture.usingpublicppg || sample.pushcapture.usesdkaspi) && sample.pushcapture.appid == "") {
  185
+        alert("Error: Please specify an application ID.");
  186
+        return false;
  187
+    }
  188
+
  189
+    if (sample.pushcapture.usingpublicppg && sample.pushcapture.ppgurl == "") {
  190
+        alert("Error: Please specify a PPG URL.");
  191
+        return false;
  192
+    }
  193
+    if (sample.pushcapture.usingpublicppg && !sample.pushcapture.ppgurl.startsWith("http://")) {
  194
+        alert("Error: The PPG URL must start with http://.");
  195
+        return false;
  196
+    }
  197
+    if (sample.pushcapture.usingpublicppg && sample.pushcapture.ppgurl.endsWith("/")) {
  198
+        alert("Error: The PPG URL should not end with a /. One will be automatically added to the end.");
  199
+        return false;
  200
+    }
  201
+    
  202
+    if (sample.pushcapture.usesdkaspi && sample.pushcapture.piurl == "") {
  203
+        alert("Error: Please specify a Push Initiator URL.");
  204
+        return false;
  205
+    }
  206
+    if (sample.pushcapture.usesdkaspi && !sample.pushcapture.piurl.startsWith("http://") && !sample.pushcapture.piurl.startsWith("https://")) {
  207
+        alert("Error: The Push Initiator URL must start with http:// or https://.");
  208
+        return false;
  209
+    }
  210
+    if (sample.pushcapture.usesdkaspi && sample.pushcapture.piurl.endsWith("/")) {
  211
+        alert("Error: The Push Initiator URL should not end with a /. One will be automatically added to the end.");
  212
+        return false;
  213
+    }
  214
+
  215
+    return true;
  216
+};
  217
+
  218
+/**
  219
+ * Stores the configuration settings in the database.
  220
+ * 
  221
+ * @memberOf sample.pushcapture
  222
+ */
  223
+sample.pushcapture.constructor.prototype.storeConfiguration = function() {
  224
+    var opInProgressDiv = document.createElement("div");
  225
+    opInProgressDiv.id = "op-in-progress";
  226
+    opInProgressDiv.className = "full-size";
  227
+    document.body.appendChild(opInProgressDiv);
  228
+    
  229
+	document.getElementById("activityindicator").style.display = "block";
  230
+    document.getElementById("progressinfo").style.display = "block";
  231
+    document.getElementById("progressinfo").innerHTML = "Saving...";
  232
+
  233
+    sample.pushcapture.db.transaction(function(tx) {
  234
+        tx.executeSql("CREATE TABLE IF NOT EXISTS configuration (appid TEXT, piurl TEXT, "
  235
+                + "ppgurl TEXT, usesdkaspi INTEGER, usingpublicppg INTEGER, launchapp INTEGER);", [], 
  236
+                function(tx, results) {
  237
+                    sample.pushcapture.successConfigurationCreation();
  238
+                });
  239
+    });
  240
+};
  241
+
  242
+/**
  243
+ * Called after successfully creating (if it did not already exist) the configuration table in the database.
  244
+ * 
  245
+ * @memberOf sample.pushcapture
  246
+ */
  247
+sample.pushcapture.constructor.prototype.successConfigurationCreation = function() {	
  248
+    sample.pushcapture.db.readTransaction(function(tx) {
  249
+        tx.executeSql("SELECT COUNT(*) AS count FROM configuration;", [],
  250
+                sample.pushcapture.insertOrUpdateConfiguration);
  251
+    });
  252
+};
  253
+
  254
+/**