You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by bo...@apache.org on 2017/09/25 19:58:30 UTC

[cordova-android] branch 6.3.x created (now 0c475b5)

This is an automated email from the ASF dual-hosted git repository.

bowserj pushed a change to branch 6.3.x
in repository https://gitbox.apache.org/repos/asf/cordova-android.git.


      at 0c475b5  Set VERSION to 6.3.0 (via coho)

This branch includes the following new commits:

     new 2a2a11a  Update JS snapshot to version 6.3.0 (via coho)
     new 0c475b5  Set VERSION to 6.3.0 (via coho)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@cordova.apache.org" <co...@cordova.apache.org>'].

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[cordova-android] 01/02: Update JS snapshot to version 6.3.0 (via coho)

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bowserj pushed a commit to branch 6.3.x
in repository https://gitbox.apache.org/repos/asf/cordova-android.git

commit 2a2a11a7290adec283e9f60187efed901f244590
Author: Joe Bowser <bo...@apache.org>
AuthorDate: Mon Sep 25 11:37:50 2017 -0700

    Update JS snapshot to version 6.3.0 (via coho)
---
 bin/templates/project/assets/www/cordova.js | 3871 ++++++++++++++-------------
 1 file changed, 1947 insertions(+), 1924 deletions(-)

diff --git a/bin/templates/project/assets/www/cordova.js b/bin/templates/project/assets/www/cordova.js
index dc1bf5a..8b19462 100644
--- a/bin/templates/project/assets/www/cordova.js
+++ b/bin/templates/project/assets/www/cordova.js
@@ -1,5 +1,5 @@
 // Platform: android
-// 7ef9f9c03167a4dde4372d869472241b6816fee9
+// 74a4adc2d0fddb1e0cfb9be1961494ef0afc9893
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -8,9 +8,9 @@
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
-
+ 
      http://www.apache.org/licenses/LICENSE-2.0
-
+ 
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,2168 +18,2191 @@
  specific language governing permissions and limitations
  under the License.
 */
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '6.3.0';
+// file: src/scripts/require.js
+
+/*jshint -W079 */
+/*jshint -W020 */
+
+var require,
+    define;
+
 (function () {
-    var PLATFORM_VERSION_BUILD_LABEL = '6.3.0-dev';
-    // file: src/scripts/require.js
-    /* global prompt */
-    /* global atob */
-    /* eslint no-eval : 0 */
-    /* eslint no-cond-assign : 0 */
-    /* eslint valid-typeof : 0 */
-
-    var require;
-    var define;
-
-    (function () {
-        var modules = {};
-        // Stack of moduleIds currently being built.
-        var requireStack = [];
-        // Map of module ID -> index into requireStack of modules currently being built.
-        var inProgressModules = {};
-        var SEPARATOR = '.';
-
-        function build (module) {
-            var factory = module.factory;
-            var localRequire = function (id) {
+    var modules = {},
+    // Stack of moduleIds currently being built.
+        requireStack = [],
+    // Map of module ID -> index into requireStack of modules currently being built.
+        inProgressModules = {},
+        SEPARATOR = ".";
+
+
+
+    function build(module) {
+        var factory = module.factory,
+            localRequire = function (id) {
                 var resultantId = id;
-                // Its a relative path, so lop off the last portion and add the id (minus "./")
-                if (id.charAt(0) === '.') {
+                //Its a relative path, so lop off the last portion and add the id (minus "./")
+                if (id.charAt(0) === ".") {
                     resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
                 }
                 return require(resultantId);
             };
-            module.exports = {};
-            delete module.factory;
-            factory(localRequire, module.exports, module);
-            return module.exports;
-        }
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
 
-        require = function (id) {
-            if (!modules[id]) {
-                throw 'module ' + id + ' not found';
-            } else if (id in inProgressModules) {
-                var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
-                throw 'Cycle in require graph: ' + cycle;
-            }
-            if (modules[id].factory) {
-                try {
-                    inProgressModules[id] = requireStack.length;
-                    requireStack.push(id);
-                    return build(modules[id]);
-                } finally {
-                    delete inProgressModules[id];
-                    requireStack.pop();
-                }
+    require = function (id) {
+        if (!modules[id]) {
+            throw "module " + id + " not found";
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw "Cycle in require graph: " + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
             }
-            return modules[id].exports;
-        };
+        }
+        return modules[id].exports;
+    };
 
-        define = function (id, factory) {
-            if (modules[id]) {
-                throw 'module ' + id + ' already defined';
-            }
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw "module " + id + " already defined";
+        }
 
-            modules[id] = {
-                id: id,
-                factory: factory
-            };
+        modules[id] = {
+            id: id,
+            factory: factory
         };
+    };
 
-        define.remove = function (id) {
-            delete modules[id];
-        };
+    define.remove = function (id) {
+        delete modules[id];
+    };
 
-        define.moduleMap = modules;
-    })();
+    define.moduleMap = modules;
+})();
 
-    // Export for use in node
-    if (typeof module === 'object' && typeof require === 'function') {
-        module.exports.require = require;
-        module.exports.define = define;
+//Export for use in node
+if (typeof module === "object" && typeof require === "function") {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) {
+    throw new Error("cordova already defined");
+}
+
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {},
+    windowEventHandlers = {};
+
+document.addEventListener = function(evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] != 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
     }
+};
+
+window.addEventListener = function(evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] != 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function(evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] != "undefined") {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function(evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] != "undefined") {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
 
-    // file: src/cordova.js
-    define('cordova', function (require, exports, module) {
-
-        // Workaround for Windows 10 in hosted environment case
-        // http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
-        var HTMLElement;
-        if (window.cordova && !(window.cordova instanceof HTMLElement)) {
-            throw new Error('cordova already defined');
-        }
-
-        var channel = require('cordova/channel');
-        var platform = require('cordova/platform');
-
-        /**
-         * Intercept calls to addEventListener + removeEventListener and handle deviceready,
-         * resume, and pause events.
-         */
-        var m_document_addEventListener = document.addEventListener;
-        var m_document_removeEventListener = document.removeEventListener;
-        var m_window_addEventListener = window.addEventListener;
-        var m_window_removeEventListener = window.removeEventListener;
-
-        /**
-         * Houses custom event handlers to intercept on document + window event listeners.
-         */
-        var documentEventHandlers = {};
-        var windowEventHandlers = {};
-
-        document.addEventListener = function (evt, handler, capture) {
-            var e = evt.toLowerCase();
-            if (typeof documentEventHandlers[e] !== 'undefined') {
-                documentEventHandlers[e].subscribe(handler);
-            } else {
-                m_document_addEventListener.call(document, evt, handler, capture);
-            }
-        };
-
-        window.addEventListener = function (evt, handler, capture) {
-            var e = evt.toLowerCase();
-            if (typeof windowEventHandlers[e] !== 'undefined') {
-                windowEventHandlers[e].subscribe(handler);
-            } else {
-                m_window_addEventListener.call(window, evt, handler, capture);
-            }
-        };
-
-        document.removeEventListener = function (evt, handler, capture) {
-            var e = evt.toLowerCase();
-            // If unsubscribing from an event that is handled by a plugin
-            if (typeof documentEventHandlers[e] !== 'undefined') {
-                documentEventHandlers[e].unsubscribe(handler);
-            } else {
-                m_document_removeEventListener.call(document, evt, handler, capture);
-            }
-        };
-
-        window.removeEventListener = function (evt, handler, capture) {
-            var e = evt.toLowerCase();
-            // If unsubscribing from an event that is handled by a plugin
-            if (typeof windowEventHandlers[e] !== 'undefined') {
-                windowEventHandlers[e].unsubscribe(handler);
-            } else {
-                m_window_removeEventListener.call(window, evt, handler, capture);
+function createEvent(type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
             }
-        };
-
-        function createEvent (type, data) {
-            var event = document.createEvent('Events');
-            event.initEvent(type, false, false);
-            if (data) {
-                for (var i in data) {
-                    if (data.hasOwnProperty(i)) {
-                        event[i] = data[i];
+        }
+    }
+    return event;
+}
+
+
+var cordova = {
+    define:define,
+    require:require,
+    version:PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion:PLATFORM_VERSION_BUILD_LABEL,
+    platformId:platform.id,
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler:function(event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler:function(event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler:function(event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler:function(event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler:function(event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function() {
+        return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+        'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function(type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] != 'undefined') {
+            if( bNoDetach ) {
+                documentEventHandlers[type].fire(evt);
+            }
+            else {
+                setTimeout(function() {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type == 'deviceready') {
+                        document.dispatchEvent(evt);
                     }
-                }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
             }
-            return event;
+        } else {
+            document.dispatchEvent(evt);
         }
-
-        var cordova = {
-            define: define,
-            require: require,
-            version: PLATFORM_VERSION_BUILD_LABEL,
-            platformVersion: PLATFORM_VERSION_BUILD_LABEL,
-            platformId: platform.id,
-            /**
-             * Methods to add/remove your own addEventListener hijacking on document + window.
-             */
-            addWindowEventHandler: function (event) {
-                return (windowEventHandlers[event] = channel.create(event));
-            },
-            addStickyDocumentEventHandler: function (event) {
-                return (documentEventHandlers[event] = channel.createSticky(event));
-            },
-            addDocumentEventHandler: function (event) {
-                return (documentEventHandlers[event] = channel.create(event));
-            },
-            removeWindowEventHandler: function (event) {
-                delete windowEventHandlers[event];
-            },
-            removeDocumentEventHandler: function (event) {
-                delete documentEventHandlers[event];
-            },
-            /**
-             * Retrieve original event handlers that were replaced by Cordova
-             *
-             * @return object
-             */
-            getOriginalHandlers: function () {
-                return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
-                    'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
-            },
-            /**
-             * Method to fire event from native code
-             * bNoDetach is required for events which cause an exception which needs to be caught in native code
-             */
-            fireDocumentEvent: function (type, data, bNoDetach) {
-                var evt = createEvent(type, data);
-                if (typeof documentEventHandlers[type] !== 'undefined') {
-                    if (bNoDetach) {
-                        documentEventHandlers[type].fire(evt);
-                    } else {
-                        setTimeout(function () {
-                            // Fire deviceready on listeners that were registered before cordova.js was loaded.
-                            if (type === 'deviceready') {
-                                document.dispatchEvent(evt);
-                            }
-                            documentEventHandlers[type].fire(evt);
-                        }, 0);
-                    }
-                } else {
-                    document.dispatchEvent(evt);
-                }
-            },
-            fireWindowEvent: function (type, data) {
-                var evt = createEvent(type, data);
-                if (typeof windowEventHandlers[type] !== 'undefined') {
-                    setTimeout(function () {
-                        windowEventHandlers[type].fire(evt);
-                    }, 0);
-                } else {
-                    window.dispatchEvent(evt);
+    },
+    fireWindowEvent: function(type, data) {
+        var evt = createEvent(type,data);
+        if (typeof windowEventHandlers[type] != 'undefined') {
+            setTimeout(function() {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks:  {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function(callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function(callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status == cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
                 }
-            },
-
-            /**
-             * Plugin callback mechanism.
-             */
-            // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
-            // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
-            callbackId: Math.floor(Math.random() * 2000000000),
-            callbacks: {},
-            callbackStatus: {
-                NO_RESULT: 0,
-                OK: 1,
-                CLASS_NOT_FOUND_EXCEPTION: 2,
-                ILLEGAL_ACCESS_EXCEPTION: 3,
-                INSTANTIATION_EXCEPTION: 4,
-                MALFORMED_URL_EXCEPTION: 5,
-                IO_EXCEPTION: 6,
-                INVALID_ACTION: 7,
-                JSON_EXCEPTION: 8,
-                ERROR: 9
-            },
-
-            /**
-             * Called by native code when returning successful result from an action.
-             */
-            callbackSuccess: function (callbackId, args) {
-                cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
-            },
-
-            /**
-             * Called by native code when returning error result from an action.
-             */
-            callbackError: function (callbackId, args) {
-                // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
-                // Derive success from status.
-                cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
-            },
-
-            /**
-             * Called by native code when returning the result from an action.
-             */
-            callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
-                try {
-                    var callback = cordova.callbacks[callbackId];
-                    if (callback) {
-                        if (isSuccess && status === cordova.callbackStatus.OK) {
-                            callback.success && callback.success.apply(null, args);
-                        } else if (!isSuccess) {
-                            callback.fail && callback.fail.apply(null, args);
-                        }
-                        /*
-                        else
-                            Note, this case is intentionally not caught.
-                            this can happen if isSuccess is true, but callbackStatus is NO_RESULT
-                            which is used to remove a callback from the list without calling the callbacks
-                            typically keepCallback is false in this case
-                        */
-                        // Clear callback if not expecting any more results
-                        if (!keepCallback) {
-                            delete cordova.callbacks[callbackId];
-                        }
-                    }
-                } catch (err) {
-                    var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
-                    console && console.log && console.log(msg);
-                    cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
-                    throw err;
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
                 }
-            },
-            addConstructor: function (func) {
-                channel.onCordovaReady.subscribe(function () {
-                    try {
-                        func();
-                    } catch (e) {
-                        console.log('Failed to run constructor: ' + e);
-                    }
-                });
             }
-        };
-
-        module.exports = cordova;
+        }
+        catch (err) {
+            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
+            console && console.log && console.log(msg);
+            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function(func) {
+        channel.onCordovaReady.subscribe(function() {
+            try {
+                func();
+            } catch(e) {
+                console.log("Failed to run constructor: " + e);
+            }
+        });
+    }
+};
 
-    });
 
-    // file: /Users/maj/src/cordova-android/cordova-js-src/android/nativeapiprovider.js
-    define('cordova/android/nativeapiprovider', function (require, exports, module) {
+module.exports = cordova;
 
-        /**
-         * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
-         */
+});
 
-        var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
-        var currentApi = nativeApi;
-
-        module.exports = {
-            get: function () { return currentApi; },
-            setPreferPrompt: function (value) {
-                currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
-            },
-            // Used only by tests.
-            set: function (value) {
-                currentApi = value;
-            }
-        };
+// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
 
-    });
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
 
-    // file: /Users/maj/src/cordova-android/cordova-js-src/android/promptbasednativeapi.js
-    define('cordova/android/promptbasednativeapi', function (require, exports, module) {
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
 
-        /**
-         * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
-         * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
-         */
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
+
+});
+
+// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
 
-        module.exports = {
-            exec: function (bridgeSecret, service, action, callbackId, argsJson) {
-                return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
-            },
-            setNativeToJsBridgeMode: function (bridgeSecret, value) {
-                prompt(value, 'gap_bridge_mode:' + bridgeSecret);
-            },
-            retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
-                return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
-            }
-        };
+});
 
-    });
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
 
-    // file: src/common/argscheck.js
-    define('cordova/argscheck', function (require, exports, module) {
+var utils = require('cordova/utils');
 
-        var utils = require('cordova/utils');
+var moduleExports = module.exports;
 
-        var moduleExports = module.exports;
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
 
-        var typeMap = {
-            'A': 'Array',
-            'D': 'Date',
-            'N': 'Number',
-            'S': 'String',
-            'F': 'Function',
-            'O': 'Object'
-        };
+function extractParamName(callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
 
-        function extractParamName (callee, argIndex) {
-            return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+function checkArgs(spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i),
+            cUpper = c.toUpperCase(),
+            arg = args[i];
+        // Asterix means allow anything.
+        if (c == '*') {
+            continue;
         }
-
-        function checkArgs (spec, functionName, args, opt_callee) {
-            if (!moduleExports.enableChecks) {
-                return;
-            }
-            var errMsg = null;
-            var typeName;
-            for (var i = 0; i < spec.length; ++i) {
-                var c = spec.charAt(i);
-                var cUpper = c.toUpperCase();
-                var arg = args[i];
-                // Asterix means allow anything.
-                if (c === '*') {
-                    continue;
-                }
-                typeName = utils.typeName(arg);
-                if ((arg === null || arg === undefined) && c === cUpper) {
-                    continue;
-                }
-                if (typeName !== typeMap[cUpper]) {
-                    errMsg = 'Expected ' + typeMap[cUpper];
-                    break;
-                }
-            }
-            if (errMsg) {
-                errMsg += ', but got ' + typeName + '.';
-                errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
-                // Don't log when running unit tests.
-                if (typeof jasmine === 'undefined') {
-                    console.error(errMsg);
-                }
-                throw TypeError(errMsg);
-            }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c == cUpper) {
+            continue;
         }
-
-        function getValue (value, defaultValue) {
-            return value === undefined ? defaultValue : value;
+        if (typeName != typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
         }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine == 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
 
-        moduleExports.checkArgs = checkArgs;
-        moduleExports.getValue = getValue;
-        moduleExports.enableChecks = true;
-
-    });
-
-    // file: src/common/base64.js
-    define('cordova/base64', function (require, exports, module) {
-
-        var base64 = exports;
+function getValue(value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
 
-        base64.fromArrayBuffer = function (arrayBuffer) {
-            var array = new Uint8Array(arrayBuffer);
-            return uint8ToBase64(array);
-        };
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
 
-        base64.toArrayBuffer = function (str) {
-            var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.alloc(str, 'base64').toString('binary');
-            var arrayBuffer = new ArrayBuffer(decodedStr.length);
-            var array = new Uint8Array(arrayBuffer);
-            for (var i = 0, len = decodedStr.length; i < len; i++) {
-                array[i] = decodedStr.charCodeAt(i);
-            }
-            return arrayBuffer;
-        };
 
-        // ------------------------------------------------------------------------------
+});
 
-        /* This code is based on the performance tests at http://jsperf.com/b64tests
-         * This 12-bit-at-a-time algorithm was the best performing version on all
-         * platforms tested.
-         */
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
 
-        var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-        var b64_12bit;
+var base64 = exports;
 
-        var b64_12bitTable = function () {
-            b64_12bit = [];
-            for (var i = 0; i < 64; i++) {
-                for (var j = 0; j < 64; j++) {
-                    b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
-                }
-            }
-            b64_12bitTable = function () { return b64_12bit; };
-            return b64_12bit;
-        };
+base64.fromArrayBuffer = function(arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
 
-        function uint8ToBase64 (rawData) {
-            var numBytes = rawData.byteLength;
-            var output = '';
-            var segment;
-            var table = b64_12bitTable();
-            for (var i = 0; i < numBytes - 2; i += 3) {
-                segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
-                output += table[segment >> 12];
-                output += table[segment & 0xfff];
-            }
-            if (numBytes - i === 2) {
-                segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
-                output += table[segment >> 12];
-                output += b64_6bit[(segment & 0xfff) >> 6];
-                output += '=';
-            } else if (numBytes - i === 1) {
-                segment = (rawData[i] << 16);
-                output += table[segment >> 12];
-                output += '==';
-            }
-            return output;
-        }
+base64.toArrayBuffer = function(str) {
+    var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i=0, len=decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
 
-    });
+//------------------------------------------------------------------------------
 
-    // file: src/common/builder.js
-    define('cordova/builder', function (require, exports, module) {
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
 
-        var utils = require('cordova/utils');
+var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var b64_12bit;
 
-        function each (objects, func, context) {
-            for (var prop in objects) {
-                if (objects.hasOwnProperty(prop)) {
-                    func.apply(context, [objects[prop], prop]);
-                }
-            }
+var b64_12bitTable = function() {
+    b64_12bit = [];
+    for (var i=0; i<64; i++) {
+        for (var j=0; j<64; j++) {
+            b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j];
         }
+    }
+    b64_12bitTable = function() { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64(rawData) {
+    var numBytes = rawData.byteLength;
+    var output="";
+    var segment;
+    var table = b64_12bitTable();
+    for (var i=0;i<numBytes-2;i+=3) {
+        segment = (rawData[i] << 16) + (rawData[i+1] << 8) + rawData[i+2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i == 2) {
+        segment = (rawData[i] << 16) + (rawData[i+1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i == 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
 
-        function clobber (obj, key, value) {
-            exports.replaceHookForTesting(obj, key);
-            var needsProperty = false;
-            try {
-                obj[key] = value;
-            } catch (e) {
-                needsProperty = true;
-            }
-            // Getters can only be overridden by getters.
-            if (needsProperty || obj[key] !== value) {
-                utils.defineGetter(obj, key, function () {
-                    return value;
-                });
-            }
-        }
+});
 
-        function assignOrWrapInDeprecateGetter (obj, key, value, message) {
-            if (message) {
-                utils.defineGetter(obj, key, function () {
-                    console.log(message);
-                    delete obj[key];
-                    clobber(obj, key, value);
-                    return value;
-                });
-            } else {
-                clobber(obj, key, value);
-            }
-        }
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
 
-        function include (parent, objects, clobber, merge) {
-            each(objects, function (obj, key) {
-                try {
-                    var result = obj.path ? require(obj.path) : {};
-
-                    if (clobber) {
-                        // Clobber if it doesn't exist.
-                        if (typeof parent[key] === 'undefined') {
-                            assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
-                        } else if (typeof obj.path !== 'undefined') {
-                            // If merging, merge properties onto parent, otherwise, clobber.
-                            if (merge) {
-                                recursiveMerge(parent[key], result);
-                            } else {
-                                assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
-                            }
-                        }
-                        result = parent[key];
-                    } else {
-                        // Overwrite if not currently defined.
-                        if (typeof parent[key] === 'undefined') {
-                            assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
-                        } else {
-                            // Set result to what already exists, so we can build children into it if they exist.
-                            result = parent[key];
-                        }
-                    }
+var utils = require('cordova/utils');
 
-                    if (obj.children) {
-                        include(result, obj.children, clobber, merge);
-                    }
-                } catch (e) {
-                    utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
-                }
-            });
+function each(objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
         }
-
-        /**
-         * Merge properties from one object onto another recursively.  Properties from
-         * the src object will overwrite existing target property.
-         *
-         * @param target Object to merge properties into.
-         * @param src Object to merge properties from.
-         */
-        function recursiveMerge (target, src) {
-            for (var prop in src) {
-                if (src.hasOwnProperty(prop)) {
-                    if (target.prototype && target.prototype.constructor === target) {
-                        // If the target object is a constructor override off prototype.
-                        clobber(target.prototype, prop, src[prop]);
+    }
+}
+
+function clobber(obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function() {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter(obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function() {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include(parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
                     } else {
-                        if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
-                            recursiveMerge(target[prop], src[prop]);
-                        } else {
-                            clobber(target, prop, src[prop]);
-                        }
-                    }
-                }
-            }
-        }
-
-        exports.buildIntoButDoNotClobber = function (objects, target) {
-            include(target, objects, false, false);
-        };
-        exports.buildIntoAndClobber = function (objects, target) {
-            include(target, objects, true, false);
-        };
-        exports.buildIntoAndMerge = function (objects, target) {
-            include(target, objects, true, true);
-        };
-        exports.recursiveMerge = recursiveMerge;
-        exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
-        exports.replaceHookForTesting = function () {};
-
-    });
-
-    // file: src/common/channel.js
-    define('cordova/channel', function (require, exports, module) {
-
-        var utils = require('cordova/utils');
-        var nextGuid = 1;
-
-        /**
-         * Custom pub-sub "channel" that can have functions subscribed to it
-         * This object is used to define and control firing of events for
-         * cordova initialization, as well as for custom events thereafter.
-         *
-         * The order of events during page load and Cordova startup is as follows:
-         *
-         * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
-         * onNativeReady*              Internal event that indicates the Cordova native side is ready.
-         * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
-         * onDeviceReady*              User event fired to indicate that Cordova is ready
-         * onResume                    User event fired to indicate a start/resume lifecycle event
-         * onPause                     User event fired to indicate a pause lifecycle event
-         *
-         * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
-         * All listeners that subscribe after the event is fired will be executed right away.
-         *
-         * The only Cordova events that user code should register for are:
-         *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
-         *      pause                 App has moved to background
-         *      resume                App has returned to foreground
-         *
-         * Listeners can be registered as:
-         *      document.addEventListener("deviceready", myDeviceReadyListener, false);
-         *      document.addEventListener("resume", myResumeListener, false);
-         *      document.addEventListener("pause", myPauseListener, false);
-         *
-         * The DOM lifecycle events should be used for saving and restoring state
-         *      window.onload
-         *      window.onunload
-         *
-         */
-
-        /**
-         * Channel
-         * @constructor
-         * @param type  String the channel name
-         */
-        var Channel = function (type, sticky) {
-            this.type = type;
-            // Map of guid -> function.
-            this.handlers = {};
-            // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
-            this.state = sticky ? 1 : 0;
-            // Used in sticky mode to remember args passed to fire().
-            this.fireArgs = null;
-            // Used by onHasSubscribersChange to know if there are any listeners.
-            this.numHandlers = 0;
-            // Function that is called when the first listener is subscribed, or when
-            // the last listener is unsubscribed.
-            this.onHasSubscribersChange = null;
-        };
-        var channel = {
-            /**
-             * Calls the provided function only after all of the channels specified
-             * have been fired. All channels must be sticky channels.
-             */
-            join: function (h, c) {
-                var len = c.length;
-                var i = len;
-                var f = function () {
-                    if (!(--i)) h();
-                };
-                for (var j = 0; j < len; j++) {
-                    if (c[j].state === 0) {
-                        throw Error('Can only use join with sticky channels.');
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
                     }
-                    c[j].subscribe(f);
                 }
-                if (!len) h();
-            },
-            create: function (type) {
-                return (channel[type] = new Channel(type, false));
-            },
-            createSticky: function (type) {
-                return (channel[type] = new Channel(type, true));
-            },
-
-            /**
-             * cordova Channels that must fire before "deviceready" is fired.
-             */
-            deviceReadyChannelsArray: [],
-            deviceReadyChannelsMap: {},
-
-            /**
-             * Indicate that a feature needs to be initialized before it is ready to be used.
-             * This holds up Cordova's "deviceready" event until the feature has been initialized
-             * and Cordova.initComplete(feature) is called.
-             *
-             * @param feature {String}     The unique feature name
-             */
-            waitForInitialization: function (feature) {
-                if (feature) {
-                    var c = channel[feature] || this.createSticky(feature);
-                    this.deviceReadyChannelsMap[feature] = c;
-                    this.deviceReadyChannelsArray.push(c);
-                }
-            },
-
-            /**
-             * Indicate that initialization code has completed and the feature is ready to be used.
-             *
-             * @param feature {String}     The unique feature name
-             */
-            initializationComplete: function (feature) {
-                var c = this.deviceReadyChannelsMap[feature];
-                if (c) {
-                    c.fire();
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] == 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
                 }
             }
-        };
 
-        function checkSubscriptionArgument (argument) {
-            if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
-                throw new Error(
-                    'Must provide a function or an EventListener object ' +
-                'implementing the handleEvent interface.'
-                );
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
             }
+        } catch(e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
         }
-
-        /**
-         * Subscribes the given function to the channel. Any time that
-         * Channel.fire is called so too will the function.
-         * Optionally specify an execution context for the function
-         * and a guid that can be used to stop subscribing to the channel.
-         * Returns the guid.
-         */
-        Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
-            checkSubscriptionArgument(eventListenerOrFunction);
-            var handleEvent, guid;
-
-            if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
-                // Received an EventListener object implementing the handleEvent interface
-                handleEvent = eventListenerOrFunction.handleEvent;
-                eventListener = eventListenerOrFunction;
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge(target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
             } else {
-                // Received a function to handle event
-                handleEvent = eventListenerOrFunction;
-            }
-
-            if (this.state === 2) {
-                handleEvent.apply(eventListener || this, this.fireArgs);
-                return;
-            }
-
-            guid = eventListenerOrFunction.observer_guid;
-            if (typeof eventListener === 'object') {
-                handleEvent = utils.close(eventListener, handleEvent);
-            }
-
-            if (!guid) {
-                // First time any channel has seen this subscriber
-                guid = '' + nextGuid++;
-            }
-            handleEvent.observer_guid = guid;
-            eventListenerOrFunction.observer_guid = guid;
-
-            // Don't add the same handler more than once.
-            if (!this.handlers[guid]) {
-                this.handlers[guid] = handleEvent;
-                this.numHandlers++;
-                if (this.numHandlers === 1) {
-                    this.onHasSubscribersChange && this.onHasSubscribersChange();
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
                 }
             }
-        };
-
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function(objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function(objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function(objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function() {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils'),
+    nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function(type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+},
+    channel = {
         /**
-         * Unsubscribes the function with the given guid from the channel.
+         * Calls the provided function only after all of the channels specified
+         * have been fired. All channels must be sticky channels.
          */
-        Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
-            checkSubscriptionArgument(eventListenerOrFunction);
-            var handleEvent, guid, handler;
-
-            if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
-                // Received an EventListener object implementing the handleEvent interface
-                handleEvent = eventListenerOrFunction.handleEvent;
-            } else {
-                // Received a function to handle event
-                handleEvent = eventListenerOrFunction;
-            }
-
-            guid = handleEvent.observer_guid;
-            handler = this.handlers[guid];
-            if (handler) {
-                delete this.handlers[guid];
-                this.numHandlers--;
-                if (this.numHandlers === 0) {
-                    this.onHasSubscribersChange && this.onHasSubscribersChange();
+        join: function(h, c) {
+            var len = c.length,
+                i = len,
+                f = function() {
+                    if (!(--i)) h();
+                };
+            for (var j=0; j<len; j++) {
+                if (c[j].state === 0) {
+                    throw Error('Can only use join with sticky channels.');
                 }
+                c[j].subscribe(f);
             }
-        };
+            if (!len) h();
+        },
+        create: function(type) {
+            return channel[type] = new Channel(type, false);
+        },
+        createSticky: function(type) {
+            return channel[type] = new Channel(type, true);
+        },
 
         /**
-         * Calls all functions subscribed to this channel.
+         * cordova Channels that must fire before "deviceready" is fired.
          */
-        Channel.prototype.fire = function (e) {
-            var fireArgs = Array.prototype.slice.call(arguments);
-            // Apply stickiness.
-            if (this.state === 1) {
-                this.state = 2;
-                this.fireArgs = fireArgs;
-            }
-            if (this.numHandlers) {
-                // Copy the values first so that it is safe to modify it from within
-                // callbacks.
-                var toCall = [];
-                for (var item in this.handlers) {
-                    toCall.push(this.handlers[item]);
-                }
-                for (var i = 0; i < toCall.length; ++i) {
-                    toCall[i].apply(this, fireArgs);
-                }
-                if (this.state === 2 && this.numHandlers) {
-                    this.numHandlers = 0;
-                    this.handlers = {};
-                    this.onHasSubscribersChange && this.onHasSubscribersChange();
-                }
-            }
-        };
-
-        // defining them here so they are ready super fast!
-        // DOM event that is received when the web page is loaded and parsed.
-        channel.createSticky('onDOMContentLoaded');
-
-        // Event to indicate the Cordova native side is ready.
-        channel.createSticky('onNativeReady');
-
-        // Event to indicate that all Cordova JavaScript objects have been created
-        // and it's time to run plugin constructors.
-        channel.createSticky('onCordovaReady');
-
-        // Event to indicate that all automatically loaded JS plugins are loaded and ready.
-        // FIXME remove this
-        channel.createSticky('onPluginsReady');
-
-        // Event to indicate that Cordova is ready
-        channel.createSticky('onDeviceReady');
-
-        // Event to indicate a resume lifecycle event
-        channel.create('onResume');
-
-        // Event to indicate a pause lifecycle event
-        channel.create('onPause');
-
-        // Channels that must fire before "deviceready" is fired.
-        channel.waitForInitialization('onCordovaReady');
-        channel.waitForInitialization('onDOMContentLoaded');
-
-        module.exports = channel;
-
-    });
-
-    // file: /Users/maj/src/cordova-android/cordova-js-src/exec.js
-    define('cordova/exec', function (require, exports, module) {
+        deviceReadyChannelsArray: [],
+        deviceReadyChannelsMap: {},
 
         /**
-         * Execute a cordova command.  It is up to the native side whether this action
-         * is synchronous or asynchronous.  The native side can return:
-         *      Synchronous: PluginResult object as a JSON string
-         *      Asynchronous: Empty string ""
-         * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
-         * depending upon the result of the action.
+         * Indicate that a feature needs to be initialized before it is ready to be used.
+         * This holds up Cordova's "deviceready" event until the feature has been initialized
+         * and Cordova.initComplete(feature) is called.
          *
-         * @param {Function} success    The success callback
-         * @param {Function} fail       The fail callback
-         * @param {String} service      The name of the service to use
-         * @param {String} action       Action to be run in cordova
-         * @param {String[]} [args]     Zero or more arguments to pass to the method
+         * @param feature {String}     The unique feature name
          */
-        var cordova = require('cordova');
-        var nativeApiProvider = require('cordova/android/nativeapiprovider');
-        var utils = require('cordova/utils');
-        var base64 = require('cordova/base64');
-        var channel = require('cordova/channel');
-        var jsToNativeModes = {
-            PROMPT: 0,
-            JS_OBJECT: 1
-        };
-        var nativeToJsModes = {
-            // Polls for messages using the JS->Native bridge.
-            POLLING: 0,
-            // For LOAD_URL to be viable, it would need to have a work-around for
-            // the bug where the soft-keyboard gets dismissed when a message is sent.
-            LOAD_URL: 1,
-            // For the ONLINE_EVENT to be viable, it would need to intercept all event
-            // listeners (both through addEventListener and window.ononline) as well
-            // as set the navigator property itself.
-            ONLINE_EVENT: 2,
-            EVAL_BRIDGE: 3
-        };
-        var jsToNativeBridgeMode; // Set lazily.
-        var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
-        var pollEnabled = false;
-        var bridgeSecret = -1;
-
-        var messagesFromNative = [];
-        var isProcessing = false;
-        var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
-        var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
-
-        function androidExec (success, fail, service, action, args) {
-            if (bridgeSecret < 0) {
-                // If we ever catch this firing, we'll need to queue up exec()s
-                // and fire them once we get a secret. For now, I don't think
-                // it's possible for exec() to be called since plugins are parsed but
-                // not run until until after onNativeReady.
-                throw new Error('exec() called without bridgeSecret');
-            }
-            // Set default bridge modes if they have not already been set.
-            // By default, we use the failsafe, since addJavascriptInterface breaks too often
-            if (jsToNativeBridgeMode === undefined) {
-                androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
-            }
-
-            // If args is not provided, default to an empty array
-            args = args || [];
-
-            // Process any ArrayBuffers in the args into a string.
-            for (var i = 0; i < args.length; i++) {
-                if (utils.typeName(args[i]) === 'ArrayBuffer') {
-                    args[i] = base64.fromArrayBuffer(args[i]);
-                }
-            }
-
-            var callbackId = service + cordova.callbackId++;
-            var argsJson = JSON.stringify(args);
-            if (success || fail) {
-                cordova.callbacks[callbackId] = {success: success, fail: fail};
+        waitForInitialization: function(feature) {
+            if (feature) {
+                var c = channel[feature] || this.createSticky(feature);
+                this.deviceReadyChannelsMap[feature] = c;
+                this.deviceReadyChannelsArray.push(c);
             }
+        },
 
-            var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
-            // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
-            // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
-            if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
-                androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
-                androidExec(success, fail, service, action, args);
-                androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
-            } else if (msgs) {
-                messagesFromNative.push(msgs);
-                // Always process async to avoid exceptions messing up stack.
-                nextTick(processMessages);
+        /**
+         * Indicate that initialization code has completed and the feature is ready to be used.
+         *
+         * @param feature {String}     The unique feature name
+         */
+        initializationComplete: function(feature) {
+            var c = this.deviceReadyChannelsMap[feature];
+            if (c) {
+                c.fire();
             }
         }
+    };
+
+function checkSubscriptionArgument(argument) {
+    if (typeof argument !== "function" && typeof argument.handleEvent !== "function") {
+        throw new Error(
+                "Must provide a function or an EventListener object " +
+                "implementing the handleEvent interface."
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function(eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
 
-        androidExec.init = function () {
-            // CB-11828
-            // This failsafe checks the version of Android and if it's Jellybean, it switches it to
-            // using the Online Event bridge for communicating from Native to JS
-            //
-            // It's ugly, but it's necessary.
-            var check = navigator.userAgent.toLowerCase().match(/android\s[0-9].[0-9]/);
-            var version_code = check && check[0].match(/4.[0-3].*/);
-            if (version_code !== null && nativeToJsBridgeMode === nativeToJsModes.EVAL_BRIDGE) {
-                nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;
-            }
-
-            bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
-            channel.onNativeReady.fire();
-        };
-
-        function pollOnceFromOnlineEvent () {
-            pollOnce(true);
-        }
+    if (this.state == 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
 
-        function pollOnce (opt_fromOnlineEvent) {
-            if (bridgeSecret < 0) {
-                // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
-                // We know there's nothing to retrieve, so no need to poll.
-                return;
-            }
-            var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
-            if (msgs) {
-                messagesFromNative.push(msgs);
-                // Process sync since we know we're already top-of-stack.
-                processMessages();
-            }
-        }
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === "object") {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
 
-        function pollingTimerFunc () {
-            if (pollEnabled) {
-                pollOnce();
-                setTimeout(pollingTimerFunc, 50);
-            }
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers == 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
         }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function(eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
 
-        function hookOnlineApis () {
-            function proxyEvent (e) {
-                cordova.fireWindowEvent(e.type);
-            }
-            // The network module takes care of firing online and offline events.
-            // It currently fires them only on document though, so we bridge them
-            // to window here (while first listening for exec()-releated online/offline
-            // events).
-            window.addEventListener('online', pollOnceFromOnlineEvent, false);
-            window.addEventListener('offline', pollOnceFromOnlineEvent, false);
-            cordova.addWindowEventHandler('online');
-            cordova.addWindowEventHandler('offline');
-            document.addEventListener('online', proxyEvent, false);
-            document.addEventListener('offline', proxyEvent, false);
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
         }
-
-        hookOnlineApis();
-
-        androidExec.jsToNativeModes = jsToNativeModes;
-        androidExec.nativeToJsModes = nativeToJsModes;
-
-        androidExec.setJsToNativeBridgeMode = function (mode) {
-            if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
-                mode = jsToNativeModes.PROMPT;
-            }
-            nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
-            jsToNativeBridgeMode = mode;
-        };
-
-        androidExec.setNativeToJsBridgeMode = function (mode) {
-            if (mode === nativeToJsBridgeMode) {
-                return;
-            }
-            if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
-                pollEnabled = false;
-            }
-
-            nativeToJsBridgeMode = mode;
-            // Tell the native side to switch modes.
-            // Otherwise, it will be set by androidExec.init()
-            if (bridgeSecret >= 0) {
-                nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
-            }
-
-            if (mode === nativeToJsModes.POLLING) {
-                pollEnabled = true;
-                setTimeout(pollingTimerFunc, 1);
-            }
-        };
-
-        function buildPayload (payload, message) {
-            var payloadKind = message.charAt(0);
-            if (payloadKind === 's') {
-                payload.push(message.slice(1));
-            } else if (payloadKind === 't') {
-                payload.push(true);
-            } else if (payloadKind === 'f') {
-                payload.push(false);
-            } else if (payloadKind === 'N') {
-                payload.push(null);
-            } else if (payloadKind === 'n') {
-                payload.push(+message.slice(1));
-            } else if (payloadKind === 'A') {
-                var data = message.slice(1);
-                payload.push(base64.toArrayBuffer(data));
-            } else if (payloadKind === 'S') {
-                payload.push(window.atob(message.slice(1)));
-            } else if (payloadKind === 'M') {
-                var multipartMessages = message.slice(1);
-                while (multipartMessages !== '') {
-                    var spaceIdx = multipartMessages.indexOf(' ');
-                    var msgLen = +multipartMessages.slice(0, spaceIdx);
-                    var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
-                    multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
-                    buildPayload(payload, multipartMessage);
-                }
-            } else {
-                payload.push(JSON.parse(message));
-            }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function(e) {
+    var fail = false,
+        fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state == 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
         }
-
-        // Processes a single message, as encoded by NativeToJsMessageQueue.java.
-        function processMessage (message) {
-            var firstChar = message.charAt(0);
-            if (firstChar === 'J') {
-                // This is deprecated on the .java side. It doesn't work with CSP enabled.
-                eval(message.slice(1));
-            } else if (firstChar === 'S' || firstChar === 'F') {
-                var success = firstChar === 'S';
-                var keepCallback = message.charAt(1) === '1';
-                var spaceIdx = message.indexOf(' ', 2);
-                var status = +message.slice(2, spaceIdx);
-                var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
-                var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
-                var payloadMessage = message.slice(nextSpaceIdx + 1);
-                var payload = [];
-                buildPayload(payload, payloadMessage);
-                cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
-            } else {
-                console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
-            }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
         }
-
-        function processMessages () {
-            // Check for the reentrant case.
-            if (isProcessing) {
-                return;
-            }
-            if (messagesFromNative.length === 0) {
-                return;
-            }
-            isProcessing = true;
-            try {
-                var msg = popMessageFromQueue();
-                // The Java side can send a * message to indicate that it
-                // still has messages waiting to be retrieved.
-                if (msg === '*' && messagesFromNative.length === 0) {
-                    nextTick(pollOnce);
-                    return;
-                }
-                processMessage(msg);
-            } finally {
-                isProcessing = false;
-                if (messagesFromNative.length > 0) {
-                    nextTick(processMessages);
-                }
-            }
+        if (this.state == 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
         }
+    }
+};
+
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1
+    },
+    nativeToJsModes = {
+        // Polls for messages using the JS->Native bridge.
+        POLLING: 0,
+        // For LOAD_URL to be viable, it would need to have a work-around for
+        // the bug where the soft-keyboard gets dismissed when a message is sent.
+        LOAD_URL: 1,
+        // For the ONLINE_EVENT to be viable, it would need to intercept all event
+        // listeners (both through addEventListener and window.ononline) as well
+        // as set the navigator property itself.
+        ONLINE_EVENT: 2,
+        EVAL_BRIDGE: 3
+    },
+    jsToNativeBridgeMode,  // Set lazily.
+    nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
+    pollEnabled = false,
+    bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
+
+function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
+    // Set default bridge modes if they have not already been set.
+    // By default, we use the failsafe, since addJavascriptInterface breaks too often
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    }
 
-        function popMessageFromQueue () {
-            var messageBatch = messagesFromNative.shift();
-            if (messageBatch === '*') {
-                return '*';
-            }
+    // If args is not provided, default to an empty array
+    args = args || [];
 
-            var spaceIdx = messageBatch.indexOf(' ');
-            var msgLen = +messageBatch.slice(0, spaceIdx);
-            var message = messageBatch.substr(spaceIdx + 1, msgLen);
-            messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
-            if (messageBatch) {
-                messagesFromNative.unshift(messageBatch);
-            }
-            return message;
+    // Process any ArrayBuffers in the args into a string.
+    for (var i = 0; i < args.length; i++) {
+        if (utils.typeName(args[i]) == 'ArrayBuffer') {
+            args[i] = base64.fromArrayBuffer(args[i]);
         }
+    }
 
-        module.exports = androidExec;
-
-    });
-
-    // file: src/common/exec/proxy.js
-    define('cordova/exec/proxy', function (require, exports, module) {
-
-        // internal map of proxy function
-        var CommandProxyMap = {};
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
 
-        module.exports = {
+    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    } else if (msgs) {
+        messagesFromNative.push(msgs);
+        // Always process async to avoid exceptions messing up stack.
+        nextTick(processMessages);
+    }
+}
+
+androidExec.init = function() {
+    //CB-11828
+    //This failsafe checks the version of Android and if it's Jellybean, it switches it to
+    //using the Online Event bridge for communicating from Native to JS
+    //
+    //It's ugly, but it's necessary.
+    var check = navigator.userAgent.toLowerCase().match(/android\s[0-9].[0-9]/);
+    var version_code = check && check[0].match(/4.[0-3].*/);
+    if (version_code != null && nativeToJsBridgeMode == nativeToJsModes.EVAL_BRIDGE) {
+      nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;
+    }
 
-            // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
-            add: function (id, proxyObj) {
-                console.log('adding proxy for ' + id);
-                CommandProxyMap[id] = proxyObj;
-                return proxyObj;
-            },
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
 
-            // cordova.commandProxy.remove("Accelerometer");
-            remove: function (id) {
-                var proxy = CommandProxyMap[id];
-                delete CommandProxyMap[id];
-                CommandProxyMap[id] = null;
-                return proxy;
-            },
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
 
-            get: function (service, action) {
-                return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
-            }
-        };
-    });
-
-    // file: src/common/init.js
-    define('cordova/init', function (require, exports, module) {
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+    if (msgs) {
+        messagesFromNative.push(msgs);
+        // Process sync since we know we're already top-of-stack.
+        processMessages();
+    }
+}
 
-        var channel = require('cordova/channel');
-        var cordova = require('cordova');
-        var modulemapper = require('cordova/modulemapper');
-        var platform = require('cordova/platform');
-        var pluginloader = require('cordova/pluginloader');
-        var utils = require('cordova/utils');
+function pollingTimerFunc() {
+    if (pollEnabled) {
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
+    }
+}
 
-        var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+function hookOnlineApis() {
+    function proxyEvent(e) {
+        cordova.fireWindowEvent(e.type);
+    }
+    // The network module takes care of firing online and offline events.
+    // It currently fires them only on document though, so we bridge them
+    // to window here (while first listening for exec()-releated online/offline
+    // events).
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+    cordova.addWindowEventHandler('online');
+    cordova.addWindowEventHandler('offline');
+    document.addEventListener('online', proxyEvent, false);
+    document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+        mode = jsToNativeModes.PROMPT;
+    }
+    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
+    jsToNativeBridgeMode = mode;
+};
 
-        function logUnfiredChannels (arr) {
-            for (var i = 0; i < arr.length; ++i) {
-                if (arr[i].state !== 2) {
-                    console.log('Channel not fired: ' + arr[i].type);
-                }
-            }
-        }
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
+        pollEnabled = false;
+    }
 
-        window.setTimeout(function () {
-            if (channel.onDeviceReady.state !== 2) {
-                console.log('deviceready has not fired after 5 seconds.');
-                logUnfiredChannels(platformInitChannelsArray);
-                logUnfiredChannels(channel.deviceReadyChannelsArray);
-            }
-        }, 5000);
-
-        // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
-        // We replace it so that properties that can't be clobbered can instead be overridden.
-        function replaceNavigator (origNavigator) {
-            var CordovaNavigator = function () {};
-            CordovaNavigator.prototype = origNavigator;
-            var newNavigator = new CordovaNavigator();
-            // This work-around really only applies to new APIs that are newer than Function.bind.
-            // Without it, APIs such as getGamepads() break.
-            if (CordovaNavigator.bind) {
-                for (var key in origNavigator) {
-                    if (typeof origNavigator[key] === 'function') {
-                        newNavigator[key] = origNavigator[key].bind(origNavigator);
-                    } else {
-                        (function (k) {
-                            utils.defineGetterSetter(newNavigator, key, function () {
-                                return origNavigator[k];
-                            });
-                        })(key);
-                    }
-                }
-            }
-            return newNavigator;
-        }
+    nativeToJsBridgeMode = mode;
+    // Tell the native side to switch modes.
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
 
-        if (window.navigator) {
-            window.navigator = replaceNavigator(window.navigator);
+    if (mode == nativeToJsModes.POLLING) {
+        pollEnabled = true;
+        setTimeout(pollingTimerFunc, 1);
+    }
+};
+
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        payload.push(base64.toArrayBuffer(data));
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
         }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    var firstChar = message.charAt(0);
+    if (firstChar == 'J') {
+        // This is deprecated on the .java side. It doesn't work with CSP enabled.
+        eval(message.slice(1));
+    } else if (firstChar == 'S' || firstChar == 'F') {
+        var success = firstChar == 'S';
+        var keepCallback = message.charAt(1) == '1';
+        var spaceIdx = message.indexOf(' ', 2);
+        var status = +message.slice(2, spaceIdx);
+        var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+        var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+        var payloadMessage = message.slice(nextSpaceIdx + 1);
+        var payload = [];
+        buildPayload(payload, payloadMessage);
+        cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+    } else {
+        console.log("processMessage failed: invalid message: " + JSON.stringify(message));
+    }
+}
 
-        if (!window.console) {
-            window.console = {
-                log: function () {}
-            };
-        }
-        if (!window.console.warn) {
-            window.console.warn = function (msg) {
-                this.log('warn: ' + msg);
-            };
+function processMessages() {
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (messagesFromNative.length === 0) {
+        return;
+    }
+    isProcessing = true;
+    try {
+        var msg = popMessageFromQueue();
+        // The Java side can send a * message to indicate that it
+        // still has messages waiting to be retrieved.
+        if (msg == '*' && messagesFromNative.length === 0) {
+            nextTick(pollOnce);
+            return;
         }
-
-        // Register pause, resume and deviceready channels as events on document.
-        channel.onPause = cordova.addDocumentEventHandler('pause');
-        channel.onResume = cordova.addDocumentEventHandler('resume');
-        channel.onActivated = cordova.addDocumentEventHandler('activated');
-        channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
-
-        // Listen for DOMContentLoaded and notify our channel subscribers.
-        if (document.readyState === 'complete' || document.readyState === 'interactive') {
-            channel.onDOMContentLoaded.fire();
-        } else {
-            document.addEventListener('DOMContentLoaded', function () {
-                channel.onDOMContentLoaded.fire();
-            }, false);
+        processMessage(msg);
+    } finally {
+        isProcessing = false;
+        if (messagesFromNative.length > 0) {
+            nextTick(processMessages);
         }
+    }
+}
 
-        // _nativeReady is global variable that the native side can set
-        // to signify that the native code is ready. It is a global since
-        // it may be called before any cordova JS is ready.
-        if (window._nativeReady) {
-            channel.onNativeReady.fire();
-        }
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
 
-        modulemapper.clobbers('cordova', 'cordova');
-        modulemapper.clobbers('cordova/exec', 'cordova.exec');
-        modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
 
-        // Call the platform-specific initialization.
-        platform.bootstrap && platform.bootstrap();
+module.exports = androidExec;
 
-        // Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
-        // The delay allows the attached modules to be defined before the plugin loader looks for them.
-        setTimeout(function () {
-            pluginloader.load(function () {
-                channel.onPluginsReady.fire();
-            });
-        }, 0);
+});
 
-        /**
-         * Create all cordova objects once native side is ready.
-         */
-        channel.join(function () {
-            modulemapper.mapModules(window);
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
 
-            platform.initialize && platform.initialize();
 
-            // Fire event to notify that all objects are created
-            channel.onCordovaReady.fire();
+// internal map of proxy function
+var CommandProxyMap = {};
 
-            // Fire onDeviceReady event once page has fully loaded, all
-            // constructors have run and cordova info has been received from native
-            // side.
-            channel.join(function () {
-                require('cordova').fireDocumentEvent('deviceready');
-            }, channel.deviceReadyChannelsArray);
+module.exports = {
 
-        }, platformInitChannelsArray);
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add:function(id,proxyObj) {
+        console.log("adding proxy for " + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
 
-    });
+    // cordova.commandProxy.remove("Accelerometer");
+    remove:function(id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
 
-    // file: src/common/init_b.js
-    define('cordova/init_b', function (require, exports, module) {
+    get:function(service,action) {
+        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
+    }
+};
+});
 
-        var channel = require('cordova/channel');
-        var cordova = require('cordova');
-        var modulemapper = require('cordova/modulemapper');
-        var platform = require('cordova/platform');
-        var pluginloader = require('cordova/pluginloader');
-        var utils = require('cordova/utils');
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
 
-        var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
 
-        // setting exec
-        cordova.exec = require('cordova/exec');
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
 
-        function logUnfiredChannels (arr) {
-            for (var i = 0; i < arr.length; ++i) {
-                if (arr[i].state !== 2) {
-                    console.log('Channel not fired: ' + arr[i].type);
-                }
-            }
+function logUnfiredChannels(arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state != 2) {
+            console.log('Channel not fired: ' + arr[i].type);
         }
+    }
+}
 
-        window.setTimeout(function () {
-            if (channel.onDeviceReady.state !== 2) {
-                console.log('deviceready has not fired after 5 seconds.');
-                logUnfiredChannels(platformInitChannelsArray);
-                logUnfiredChannels(channel.deviceReadyChannelsArray);
-            }
-        }, 5000);
-
-        // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
-        // We replace it so that properties that can't be clobbered can instead be overridden.
-        function replaceNavigator (origNavigator) {
-            var CordovaNavigator = function () {};
-            CordovaNavigator.prototype = origNavigator;
-            var newNavigator = new CordovaNavigator();
-            // This work-around really only applies to new APIs that are newer than Function.bind.
-            // Without it, APIs such as getGamepads() break.
-            if (CordovaNavigator.bind) {
-                for (var key in origNavigator) {
-                    if (typeof origNavigator[key] === 'function') {
-                        newNavigator[key] = origNavigator[key].bind(origNavigator);
-                    } else {
-                        (function (k) {
-                            utils.defineGetterSetter(newNavigator, key, function () {
-                                return origNavigator[k];
-                            });
-                        })(key);
-                    }
-                }
+window.setTimeout(function() {
+    if (channel.onDeviceReady.state != 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+    var CordovaNavigator = function() {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] == 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            }
+            else {
+                (function(k) {
+                    utils.defineGetterSetter(newNavigator,key,function() {
+                        return origNavigator[k];
+                    });
+                })(key);
             }
-            return newNavigator;
-        }
-        if (window.navigator) {
-            window.navigator = replaceNavigator(window.navigator);
         }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function(){}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function(msg) {
+        this.log("warn: " + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function() {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function() {
+    pluginloader.load(function() {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
 
-        if (!window.console) {
-            window.console = {
-                log: function () {}
-            };
-        }
-        if (!window.console.warn) {
-            window.console.warn = function (msg) {
-                this.log('warn: ' + msg);
-            };
-        }
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+    modulemapper.mapModules(window);
 
-        // Register pause, resume and deviceready channels as events on document.
-        channel.onPause = cordova.addDocumentEventHandler('pause');
-        channel.onResume = cordova.addDocumentEventHandler('resume');
-        channel.onActivated = cordova.addDocumentEventHandler('activated');
-        channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+    platform.initialize && platform.initialize();
 
-        // Listen for DOMContentLoaded and notify our channel subscribers.
-        if (document.readyState === 'complete' || document.readyState === 'interactive') {
-            channel.onDOMContentLoaded.fire();
-        } else {
-            document.addEventListener('DOMContentLoaded', function () {
-                channel.onDOMContentLoaded.fire();
-            }, false);
-        }
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
 
-        // _nativeReady is global variable that the native side can set
-        // to signify that the native code is ready. It is a global since
-        // it may be called before any cordova JS is ready.
-        if (window._nativeReady) {
-            channel.onNativeReady.fire();
-        }
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function() {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
 
-        // Call the platform-specific initialization.
-        platform.bootstrap && platform.bootstrap();
+}, platformInitChannelsArray);
 
-        // Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
-        // The delay allows the attached modules to be defined before the plugin loader looks for them.
-        setTimeout(function () {
-            pluginloader.load(function () {
-                channel.onPluginsReady.fire();
-            });
-        }, 0);
 
-        /**
-         * Create all cordova objects once native side is ready.
-         */
-        channel.join(function () {
-            modulemapper.mapModules(window);
+});
+
+// file: src/common/init_b.js
+define("cordova/init_b", function(require, exports, module) {
 
-            platform.initialize && platform.initialize();
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
 
-            // Fire event to notify that all objects are created
-            channel.onCordovaReady.fire();
+var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
 
-            // Fire onDeviceReady event once page has fully loaded, all
-            // constructors have run and cordova info has been received from native
-            // side.
-            channel.join(function () {
-                require('cordova').fireDocumentEvent('deviceready');
-            }, channel.deviceReadyChannelsArray);
+// setting exec
+cordova.exec = require('cordova/exec');
 
-        }, platformInitChannelsArray);
+function logUnfiredChannels(arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state != 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
 
+window.setTimeout(function() {
+    if (channel.onDeviceReady.state != 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+    var CordovaNavigator = function() {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] == 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            }
+            else {
+                (function(k) {
+                    utils.defineGetterSetter(newNavigator,key,function() {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function(){}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function(msg) {
+        this.log("warn: " + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function() {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function() {
+    pluginloader.load(function() {
+        channel.onPluginsReady.fire();
     });
+}, 0);
 
-    // file: src/common/modulemapper.js
-    define('cordova/modulemapper', function (require, exports, module) {
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+    modulemapper.mapModules(window);
 
-        var builder = require('cordova/builder');
-        var moduleMap = define.moduleMap;
-        var symbolList;
-        var deprecationMap;
+    platform.initialize && platform.initialize();
 
-        exports.reset = function () {
-            symbolList = [];
-            deprecationMap = {};
-        };
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
 
-        function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
-            if (!(moduleName in moduleMap)) {
-                throw new Error('Module ' + moduleName + ' does not exist.');
-            }
-            symbolList.push(strategy, moduleName, symbolPath);
-            if (opt_deprecationMessage) {
-                deprecationMap[symbolPath] = opt_deprecationMessage;
-            }
-        }
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function() {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
 
-        // Note: Android 2.3 does have Function.bind().
-        exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
-        };
+}, platformInitChannelsArray);
 
-        exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
-        };
+});
 
-        exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
-        };
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
 
-        exports.runs = function (moduleName) {
-            addEntry('r', moduleName, null);
-        };
+var builder = require('cordova/builder'),
+    moduleMap = define.moduleMap,
+    symbolList,
+    deprecationMap;
 
-        function prepareNamespace (symbolPath, context) {
-            if (!symbolPath) {
-                return context;
-            }
-            var parts = symbolPath.split('.');
-            var cur = context;
-            for (var i = 0, part; part = parts[i]; ++i) {
-                cur = cur[part] = cur[part] || {};
-            }
-            return cur;
-        }
+exports.reset = function() {
+    symbolList = [];
+    deprecationMap = {};
+};
 
-        exports.mapModules = function (context) {
-            var origSymbols = {};
-            context.CDV_origSymbols = origSymbols;
-            for (var i = 0, len = symbolList.length; i < len; i += 3) {
-                var strategy = symbolList[i];
-                var moduleName = symbolList[i + 1];
-                var module = require(moduleName);
-                // <runs/>
-                if (strategy === 'r') {
-                    continue;
-                }
-                var symbolPath = symbolList[i + 2];
-                var lastDot = symbolPath.lastIndexOf('.');
-                var namespace = symbolPath.substr(0, lastDot);
-                var lastName = symbolPath.substr(lastDot + 1);
-
-                var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
-                var parentObj = prepareNamespace(namespace, context);
-                var target = parentObj[lastName];
-
-                if (strategy === 'm' && target) {
-                    builder.recursiveMerge(target, module);
-                } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
-                    if (!(symbolPath in origSymbols)) {
-                        origSymbols[symbolPath] = target;
-                    }
-                    builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
-                }
-            }
-        };
+function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
 
-        exports.getOriginalSymbol = function (context, symbolPath) {
-            var origSymbols = context.CDV_origSymbols;
-            if (origSymbols && (symbolPath in origSymbols)) {
-                return origSymbols[symbolPath];
-            }
-            var parts = symbolPath.split('.');
-            var obj = context;
-            for (var i = 0; i < parts.length; ++i) {
-                obj = obj && obj[parts[i]];
-            }
-            return obj;
-        };
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-        exports.reset();
+exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-    });
+exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-    // file: src/common/modulemapper_b.js
-    define('cordova/modulemapper_b', function (require, exports, module) {
+exports.runs = function(moduleName) {
+    addEntry('r', moduleName, null);
+};
 
-        var builder = require('cordova/builder');
-        var symbolList = [];
-        var deprecationMap;
+function prepareNamespace(symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) {
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function(context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy == 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy == 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
 
-        exports.reset = function () {
-            symbolList = [];
-            deprecationMap = {};
-        };
+exports.getOriginalSymbol = function(context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
 
-        function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
-            symbolList.push(strategy, moduleName, symbolPath);
-            if (opt_deprecationMessage) {
-                deprecationMap[symbolPath] = opt_deprecationMessage;
-            }
-        }
+exports.reset();
 
-        // Note: Android 2.3 does have Function.bind().
-        exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
-        };
 
-        exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
-        };
+});
 
-        exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
-            addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
-        };
+// file: src/common/modulemapper_b.js
+define("cordova/modulemapper_b", function(require, exports, module) {
 
-        exports.runs = function (moduleName) {
-            addEntry('r', moduleName, null);
-        };
+var builder = require('cordova/builder'),
+    symbolList = [],
+    deprecationMap;
 
-        function prepareNamespace (symbolPath, context) {
-            if (!symbolPath) {
-                return context;
-            }
-            var parts = symbolPath.split('.');
-            var cur = context;
-            for (var i = 0, part; part = parts[i]; ++i) {
-                cur = cur[part] = cur[part] || {};
-            }
-            return cur;
-        }
+exports.reset = function() {
+    symbolList = [];
+    deprecationMap = {};
+};
 
-        exports.mapModules = function (context) {
-            var origSymbols = {};
-            context.CDV_origSymbols = origSymbols;
-            for (var i = 0, len = symbolList.length; i < len; i += 3) {
-                var strategy = symbolList[i];
-                var moduleName = symbolList[i + 1];
-                var module = require(moduleName);
-                // <runs/>
-                if (strategy === 'r') {
-                    continue;
-                }
-                var symbolPath = symbolList[i + 2];
-                var lastDot = symbolPath.lastIndexOf('.');
-                var namespace = symbolPath.substr(0, lastDot);
-                var lastName = symbolPath.substr(lastDot + 1);
-
-                var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
-                var parentObj = prepareNamespace(namespace, context);
-                var target = parentObj[lastName];
-
-                if (strategy === 'm' && target) {
-                    builder.recursiveMerge(target, module);
-                } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
-                    if (!(symbolPath in origSymbols)) {
-                        origSymbols[symbolPath] = target;
-                    }
-                    builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
-                }
-            }
-        };
+function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
 
-        exports.getOriginalSymbol = function (context, symbolPath) {
-            var origSymbols = context.CDV_origSymbols;
-            if (origSymbols && (symbolPath in origSymbols)) {
-                return origSymbols[symbolPath];
-            }
-            var parts = symbolPath.split('.');
-            var obj = context;
-            for (var i = 0; i < parts.length; ++i) {
-                obj = obj && obj[parts[i]];
-            }
-            return obj;
-        };
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-        exports.reset();
+exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-    });
+exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
 
-    // file: /Users/maj/src/cordova-android/cordova-js-src/platform.js
-    define('cordova/platform', function (require, exports, module) {
+exports.runs = function(moduleName) {
+    addEntry('r', moduleName, null);
+};
 
-        // The last resume event that was received that had the result of a plugin call.
-        var lastResumeEvent = null;
+function prepareNamespace(symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) {
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function(context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy == 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy == 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
 
-        module.exports = {
-            id: 'android',
-            bootstrap: function () {
-                var channel = require('cordova/channel');
-                var cordova = require('cordova');
-                var exec = require('cordova/exec');
-                var modulemapper = require('cordova/modulemapper');
+exports.getOriginalSymbol = function(context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
 
-                // Get the shared secret needed to use the bridge.
-                exec.init();
+exports.reset();
 
-                // TODO: Extract this as a proper plugin.
-                modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
 
-                var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+});
 
-                // Inject a listener for the backbutton on the document.
-                var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
-                backButtonChannel.onHasSubscribersChange = function () {
-                    // If we just attached the first handler or detached the last handler,
-                    // let native know we need to override the back button.
-                    exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
-                };
+// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
 
-                // Add hardware MENU and SEARCH button handlers
-                cordova.addDocumentEventHandler('menubutton');
-                cordova.addDocumentEventHandler('searchbutton');
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
 
-                function bindButtonChannel (buttonName) {
-                    // generic button bind used for volumeup/volumedown buttons
-                    var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
-                    volumeButtonChannel.onHasSubscribersChange = function () {
-                        exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
-                    };
-                }
-                // Inject a listener for the volume buttons on the document.
-                bindButtonChannel('volumeup');
-                bindButtonChannel('volumedown');
+module.exports = {
+    id: 'android',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
 
-                // The resume event is not "sticky", but it is possible that the event
-                // will contain the result of a plugin call. We need to ensure that the
-                // plugin result is delivered even after the event is fired (CB-10498)
-                var cordovaAddEventListener = document.addEventListener;
+        // Get the shared secret needed to use the bridge.
+        exec.init();
 
-                document.addEventListener = function (evt, handler, capture) {
-                    cordovaAddEventListener(evt, handler, capture);
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
 
-                    if (evt === 'resume' && lastResumeEvent) {
-                        handler(lastResumeEvent);
-                    }
-                };
+        var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
 
-                // Let native code know we are all done on the JS side.
-                // Native code will then un-hide the WebView.
-                channel.onCordovaReady.subscribe(function () {
-                    exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
-                    exec(null, null, APP_PLUGIN_NAME, 'show', []);
-                });
-            }
+        // Inject a listener for the backbutton on the document.
+        var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+        backButtonChannel.onHasSubscribersChange = function() {
+            // If we just attached the first handler or detached the last handler,
+            // let native know we need to override the back button.
+            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
         };
 
-        function onMessageFromNative (msg) {
-            var cordova = require('cordova');
-            var action = msg.action;
-
-            switch (action) {
-            // Button events
-            case 'backbutton':
-            case 'menubutton':
-            case 'searchbutton':
-            // App life cycle events
-                break;
-            case 'pause':
-                break;
-            // Volume events
-            case 'volumedownbutton':
-            case 'volumeupbutton':
-                cordova.fireDocumentEvent(action);
-                break;
-            case 'resume':
-                if (arguments.length > 1 && msg.pendingResult) {
-                    if (arguments.length === 2) {
-                        msg.pendingResult.result = arguments[1];
-                    } else {
-                        // The plugin returned a multipart message
-                        var res = [];
-                        for (var i = 1; i < arguments.length; i++) {
-                            res.push(arguments[i]);
-                        }
-                        msg.pendingResult.result = res;
-                    }
+        // Add hardware MENU and SEARCH button handlers
+        cordova.addDocumentEventHandler('menubutton');
+        cordova.addDocumentEventHandler('searchbutton');
 
-                    // Save the plugin result so that it can be delivered to the js
-                    // even if they miss the initial firing of the event
-                    lastResumeEvent = msg;
-                }
-                cordova.fireDocumentEvent(action, msg);
-                break;
-            default:
-                throw new Error('Unknown event action ' + action);
-            }
+        function bindButtonChannel(buttonName) {
+            // generic button bind used for volumeup/volumedown buttons
+            var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+            volumeButtonChannel.onHasSubscribersChange = function() {
+                exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
+            };
         }
+        // Inject a listener for the volume buttons on the document.
+        bindButtonChannel('volumeup');
+        bindButtonChannel('volumedown');
 
-    });
+        // The resume event is not "sticky", but it is possible that the event
+        // will contain the result of a plugin call. We need to ensure that the
+        // plugin result is delivered even after the event is fired (CB-10498)
+        var cordovaAddEventListener = document.addEventListener;
+
+        document.addEventListener = function(evt, handler, capture) {
+            cordovaAddEventListener(evt, handler, capture);
 
-    // file: /Users/maj/src/cordova-android/cordova-js-src/plugin/android/app.js
-    define('cordova/plugin/android/app', function (require, exports, module) {
-
-        var exec = require('cordova/exec');
-        var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
-
-        module.exports = {
-            /**
-            * Clear the resource cache.
-            */
-            clearCache: function () {
-                exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
-            },
-
-            /**
-            * Load the url into the webview or into new browser instance.
-            *
-            * @param url           The URL to load
-            * @param props         Properties that can be passed in to the activity:
-            *      wait: int                           => wait msec before loading URL
-            *      loadingDialog: "Title,Message"      => display a native loading dialog
-            *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
-            *      clearHistory: boolean              => clear webview history (default=false)
-            *      openExternal: boolean              => open in a new browser (default=false)
-            *
-            * Example:
-            *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
-            */
-            loadUrl: function (url, props) {
-                exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
-            },
-
-            /**
-            * Cancel loadUrl that is waiting to be loaded.
-            */
-            cancelLoadUrl: function () {
-                exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
-            },
-
-            /**
-            * Clear web history in this web view.
-            * Instead of BACK button loading the previous web page, it will exit the app.
-            */
-            clearHistory: function () {
-                exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
-            },
-
-            /**
-            * Go to previous page displayed.
-            * This is the same as pressing the backbutton on Android device.
-            */
-            backHistory: function () {
-                exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
-            },
-
-            /**
-            * Override the default behavior of the Android back button.
-            * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
-            *
-            * Note: The user should not have to call this method.  Instead, when the user
-            *       registers for the "backbutton" event, this is automatically done.
-            *
-            * @param override        T=override, F=cancel override
-            */
-            overrideBackbutton: function (override) {
-                exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
-            },
-
-            /**
-            * Override the default behavior of the Android volume button.
-            * If overridden, when the volume button is pressed, the "volume[up|down]button"
-            * JavaScript event will be fired.
-            *
-            * Note: The user should not have to call this method.  Instead, when the user
-            *       registers for the "volume[up|down]button" event, this is automatically done.
-            *
-            * @param button          volumeup, volumedown
-            * @param override        T=override, F=cancel override
-            */
-            overrideButton: function (button, override) {
-                exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
-            },
-
-            /**
-            * Exit and terminate the application.
-            */
-            exitApp: function () {
-                return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
+            if (evt === 'resume' && lastResumeEvent) {
+                handler(lastResumeEvent);
             }
         };
 
-    });
-
-    // file: src/common/pluginloader.js
-    define('cordova/pluginloader', function (require, exports, module) {
-
-        var modulemapper = require('cordova/modulemapper');
-
-        // Helper function to inject a <script> tag.
-        // Exported for testing.
-        exports.injectScript = function (url, onload, onerror) {
-            var script = document.createElement('script');
-            // onload fires even when script fails loads with an error.
-            script.onload = onload;
-            // onerror fires for malformed URLs.
-            script.onerror = onerror;
-            script.src = url;
-            document.head.appendChild(script);
-        };
+        // Let native code know we are all done on the JS side.
+        // Native code will then un-hide the WebView.
+        channel.onCordovaReady.subscribe(function() {
+            exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+            exec(null, null, APP_PLUGIN_NAME, "show", []);
+        });
+    }
+};
+
+function onMessageFromNative(msg) {
+    var cordova = require('cordova');
+    var action = msg.action;
+
+    switch (action)
+    {
+        // Button events
+        case 'backbutton':
+        case 'menubutton':
+        case 'searchbutton':
+        // App life cycle events
+        case 'pause':
+        // Volume events
+        case 'volumedownbutton':
+        case 'volumeupbutton':
+            cordova.fireDocumentEvent(action);
+            break;
+        case 'resume':
+            if(arguments.length > 1 && msg.pendingResult) {
+                if(arguments.length === 2) {
+                    msg.pendingResult.result = arguments[1];
+                } else {
+                    // The plugin returned a multipart message
+                    var res = [];
+                    for(var i = 1; i < arguments.length; i++) {
+                        res.push(arguments[i]);
+                    }
+                    msg.pendingResult.result = res;
+                }
 
-        function injectIfNecessary (id, url, onload, onerror) {
-            onerror = onerror || onload;
+                // Save the plugin result so that it can be delivered to the js
+                // even if they miss the initial firing of the event
+                lastResumeEvent = msg;
+            }
+            cordova.fireDocumentEvent(action, msg);
+            break;
+        default:
+            throw new Error('Unknown event action ' + action);
+    }
+}
+
+});
+
+// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/plugin/android/app.js
+define("cordova/plugin/android/app", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
+    },
+
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
+    },
+
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
+    },
+
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
+    },
+
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
+    },
+
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
+    },
+
+    /**
+    * Override the default behavior of the Android volume button.
+    * If overridden, when the volume button is pressed, the "volume[up|down]button"
+    * JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "volume[up|down]button" event, this is automatically done.
+    *
+    * @param button          volumeup, volumedown
+    * @param override        T=override, F=cancel override
+    */
+    overrideButton:function(button, override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
+    },
+
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
+    }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function(url, onload, onerror) {
+    var script = document.createElement("script");
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary(id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) {
+        onload();
+    } else {
+        exports.injectScript(url, function() {
             if (id in define.moduleMap) {
                 onload();
             } else {
-                exports.injectScript(url, function () {
-                    if (id in define.moduleMap) {
-                        onload();
-                    } else {
-                        onerror();
-                    }
-                }, onerror);
+                onerror();
             }
-        }
-
-        function onScriptLoadingComplete (moduleList, finishPluginLoading) {
-            // Loop through all the plugins and then through their clobbers and merges.
-            for (var i = 0, module; module = moduleList[i]; i++) {
-                if (module.clobbers && module.clobbers.length) {
-                    for (var j = 0; j < module.clobbers.length; j++) {
-                        modulemapper.clobbers(module.id, module.clobbers[j]);
-                    }
-                }
-
-                if (module.merges && module.merges.length) {
-                    for (var k = 0; k < module.merges.length; k++) {
-                        modulemapper.merges(module.id, module.merges[k]);
-                    }
-                }
+        }, onerror);
+    }
+}
 
-                // Finally, if runs is truthy we want to simply require() the module.
-                if (module.runs) {
-                    modulemapper.runs(module.id);
-                }
+function onScriptLoadingComplete(moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) {
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
             }
-
-            finishPluginLoading();
         }
 
-        // Handler for the cordova_plugins.js content.
-        // See plugman's plugin_loader.js for the details of this object.
-        // This function is only called if the really is a plugins array that isn't empty.
-        // Otherwise the onerror response handler will just call finishPluginLoading().
-        function handlePluginsObject (path, moduleList, finishPluginLoading) {
-            // Now inject the scripts.
-            var scriptCounter = moduleList.length;
-
-            if (!scriptCounter) {
-                finishPluginLoading();
-                return;
-            }
-            function scriptLoadedCallback () {
-                if (!--scriptCounter) {
-                    onScriptLoadingComplete(moduleList, finishPluginLoading);
-                }
-            }
-
-            for (var i = 0; i < moduleList.length; i++) {
-                injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
             }
         }
 
-        function findCordovaPath () {
-            var path = null;
-            var scripts = document.getElementsByTagName('script');
-            var term = '/cordova.js';
-            for (var n = scripts.length - 1; n > -1; n--) {
-                var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
-                if (src.indexOf(term) === (src.length - term.length)) {
-                    path = src.substring(0, src.length - term.length) + '/';
-                    break;
-                }
-            }
-            return path;
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
         }
+    }
 
-        // Tries to load all plugins' js-modules.
-        // This is an async process, but onDeviceReady is blocked on onPluginsReady.
-        // onPluginsReady is fired when there are no plugins to load, or they are all done.
-        exports.load = function (callback) {
-            var pathPrefix = findCordovaPath();
-            if (pathPrefix === null) {
-                console.log('Could not find cordova.js script tag. Plugin loading may fail.');
-                pathPrefix = '';
-            }
-            injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
-                var moduleList = require('cordova/plugin_list');
-                handlePluginsObject(pathPrefix, moduleList, callback);
-            }, callback);
-        };
+    finishPluginLoading();
+}
 
-    });
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject(path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback() {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
 
-    // file: src/common/pluginloader_b.js
-    define('cordova/pluginloader_b', function (require, exports, module) {
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath() {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length-1; n>-1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) == (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function(callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
+        var moduleList = require("cordova/plugin_list");
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
 
-        var modulemapper = require('cordova/modulemapper');
 
-        // Handler for the cordova_plugins.js content.
-        // See plugman's plugin_loader.js for the details of this object.
-        function handlePluginsObject (moduleList) {
-            // if moduleList is not defined or empty, we've nothing to do
-            if (!moduleList || !moduleList.length) {
-                return;
-            }
+});
 
-            // Loop through all the modules and then through their clobbers and merges.
-            for (var i = 0, module; module = moduleList[i]; i++) {
-                if (module.clobbers && module.clobbers.length) {
-                    for (var j = 0; j < module.clobbers.length; j++) {
-                        modulemapper.clobbers(module.id, module.clobbers[j]);
-                    }
-                }
+// file: src/common/pluginloader_b.js
+define("cordova/pluginloader_b", function(require, exports, module) {
 
-                if (module.merges && module.merges.length) {
-                    for (var k = 0; k < module.merges.length; k++) {
-                        modulemapper.merges(module.id, module.merges[k]);
-                    }
-                }
+var modulemapper = require('cordova/modulemapper');
 
-                // Finally, if runs is truthy we want to simply require() the module.
-                if (module.runs) {
-                    modulemapper.runs(module.id);
-                }
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+function handlePluginsObject(moduleList) {
+    // if moduleList is not defined or empty, we've nothing to do
+    if (!moduleList || !moduleList.length) {
+        return;
+    }
+
+    // Loop through all the modules and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) {
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
             }
         }
 
-        // Loads all plugins' js-modules. Plugin loading is syncronous in browserified bundle
-        // but the method accepts callback to be compatible with non-browserify flow.
-        // onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
-        // no plugins to load, or they are all done.
-        exports.load = function (callback) {
-            var moduleList = require('cordova/plugin_list');
-            handlePluginsObject(moduleList);
-
-            callback();
-        };
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
 
-    });
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+}
 
-    // file: src/common/urlutil.js
-    define('cordova/urlutil', function (require, exports, module) {
+// Loads all plugins' js-modules. Plugin loading is syncronous in browserified bundle
+// but the method accepts callback to be compatible with non-browserify flow.
+// onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
+// no plugins to load, or they are all done.
+exports.load = function(callback) {
+    var moduleList = require("cordova/plugin_list");
+    handlePluginsObject(moduleList);
 
-        /**
-         * For already absolute URLs, returns what is passed in.
-         * For relative URLs, converts them to absolute ones.
-         */
-        exports.makeAbsolute = function makeAbsolute (url) {
-            var anchorEl = document.createElement('a');
-            anchorEl.href = url;
-            return anchorEl.href;
-        };
+    callback();
+};
 
-    });
 
-    // file: src/common/utils.js
-    define('cordova/utils', function (require, exports, module) {
+});
 
-        var utils = exports;
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
 
-        /**
-         * Defines a property getter / setter for obj[key].
-         */
-        utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
-            if (Object.defineProperty) {
-                var desc = {
-                    get: getFunc,
-                    configurable: true
-                };
-                if (opt_setFunc) {
-                    desc.set = opt_setFunc;
-                }
-                Object.defineProperty(obj, key, desc);
-            } else {
-                obj.__defineGetter__(key, getFunc);
-                if (opt_setFunc) {
-                    obj.__defineSetter__(key, opt_setFunc);
-                }
-            }
-        };
 
-        /**
-         * Defines a property getter for obj[key].
-         */
-        utils.defineGetter = utils.defineGetterSetter;
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute(url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
 
-        utils.arrayIndexOf = function (a, item) {
-            if (a.indexOf) {
-                return a.indexOf(item);
-            }
-            var len = a.length;
-            for (var i = 0; i < len; ++i) {
-                if (a[i] === item) {
-                    return i;
-                }
-            }
-            return -1;
-        };
 
-        /**
-         * Returns whether the item was found in the array.
-         */
-        utils.arrayRemove = function (a, item) {
-            var index = utils.arrayIndexOf(a, item);
-            if (index !== -1) {
-                a.splice(index, 1);
-            }
-            return index !== -1;
-        };
+});
 
-        utils.typeName = function (val) {
-            return Object.prototype.toString.call(val).slice(8, -1);
-        };
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
 
-        /**
-         * Returns an indication of whether the argument is an array or not
-         */
-        utils.isArray = Array.isArray ||
-                function (a) { return utils.typeName(a) === 'Array'; };
+var utils = exports;
 
-        /**
-         * Returns an indication of whether the argument is a Date or not
-         */
-        utils.isDate = function (d) {
-            return (d instanceof Date);
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
         };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
 
-        /**
-         * Does a deep clone of the object.
-         */
-        utils.clone = function (obj) {
-            if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
-                return obj;
-            }
-
-            var retVal, i;
-
-            if (utils.isArray(obj)) {
-                retVal = [];
-                for (i = 0; i < obj.length; ++i) {
-                    retVal.push(utils.clone(obj[i]));
-                }
-                return retVal;
-            }
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
 
-            retVal = {};
-            for (i in obj) {
-                // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
-                // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
-                // on cloning.
-                if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') {
-                    retVal[i] = utils.clone(obj[i]);
-                }
-            }
-            return retVal;
-        };
+utils.arrayIndexOf = function(a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] == item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function(a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index != -1) {
+        a.splice(index, 1);
+    }
+    return index != -1;
+};
+
+utils.typeName = function(val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function(a) {return utils.typeName(a) == 'Array';};
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function(d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function(obj) {
+    if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
+        return obj;
+    }
 
-        /**
-         * Returns a wrapped version of the function
-         */
-        utils.close = function (context, func, params) {
-            return function () {
-                var args = params || arguments;
-                return func.apply(context, args);
-            };
-        };
+    var retVal, i;
 
-        // ------------------------------------------------------------------------------
-        function UUIDcreatePart (length) {
-            var uuidpart = '';
-            for (var i = 0; i < length; i++) {
-                var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
-                if (uuidchar.length === 1) {
-                    uuidchar = '0' + uuidchar;
-                }
-                uuidpart += uuidchar;
-            }
-            return uuidpart;
+    if(utils.isArray(obj)){
+        retVal = [];
+        for(i = 0; i < obj.length; ++i){
+            retVal.push(utils.clone(obj[i]));
         }
+        return retVal;
+    }
 
-        /**
-         * Create a UUID
-         */
-        utils.createUUID = function () {
-            return UUIDcreatePart(4) + '-' +
+    retVal = {};
+    for(i in obj){
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if((!(i in retVal) || retVal[i] != obj[i]) && typeof obj[i] != 'undefined' && typeof obj[i] != 'unknown') {
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function(context, func, params) {
+    return function() {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+//------------------------------------------------------------------------------
+function UUIDcreatePart(length) {
+    var uuidpart = "";
+    for (var i=0; i<length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length == 1) {
+            uuidchar = "0" + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function() {
+    return UUIDcreatePart(4) + '-' +
         UUIDcreatePart(2) + '-' +
         UUIDcreatePart(2) + '-' +
         UUIDcreatePart(2) + '-' +
         UUIDcreatePart(6);
-        };
+};
+
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function() {
+    // proxy used to establish prototype chain
+    var F = function() {};
+    // extend Child from Parent
+    return function(Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function(msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
 
-        /**
-         * Extends a child object from a parent object using classical inheritance
-         * pattern.
-         */
-        utils.extend = (function () {
-            // proxy used to establish prototype chain
-            var F = function () {};
-            // extend Child from Parent
-            return function (Child, Parent) {
-
-                F.prototype = Parent.prototype;
-                Child.prototype = new F();
-                Child.__super__ = Parent.prototype;
-                Child.prototype.constructor = Child;
-            };
-        }());
 
-        /**
-         * Alerts a message in any available way: alert or console.log.
-         */
-        utils.alert = function (msg) {
-            if (window.alert) {
-                window.alert(msg);
-            } else if (console && console.log) {
-                console.log(msg);
-            }
-        };
 
-    });
 
-    window.cordova = require('cordova');
-    // file: src/scripts/bootstrap.js
 
-    require('cordova/init');
+});
 
-})();
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
"commits@cordova.apache.org" <co...@cordova.apache.org>.

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[cordova-android] 02/02: Set VERSION to 6.3.0 (via coho)

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bowserj pushed a commit to branch 6.3.x
in repository https://gitbox.apache.org/repos/asf/cordova-android.git

commit 0c475b5ec4356ceabea1b4febe3a3a24dd827c50
Author: Joe Bowser <bo...@apache.org>
AuthorDate: Mon Sep 25 11:37:50 2017 -0700

    Set VERSION to 6.3.0 (via coho)
---
 VERSION                                              | 2 +-
 bin/templates/cordova/version                        | 2 +-
 framework/build.gradle                               | 4 ++--
 framework/src/org/apache/cordova/CordovaWebView.java | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/VERSION b/VERSION
index 806c93a..798e389 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.3.0-dev
+6.3.0
diff --git a/bin/templates/cordova/version b/bin/templates/cordova/version
index 45dc047..e3c77c8 100755
--- a/bin/templates/cordova/version
+++ b/bin/templates/cordova/version
@@ -20,7 +20,7 @@
 */
 
 // Coho updates this line:
-var VERSION = "6.3.0-dev";
+var VERSION = "6.3.0";
 
 module.exports.version = VERSION;
 
diff --git a/framework/build.gradle b/framework/build.gradle
index 6f10564..df26f2f 100644
--- a/framework/build.gradle
+++ b/framework/build.gradle
@@ -129,9 +129,9 @@ bintray {
         licenses = ['Apache-2.0']
         labels = ['android', 'cordova', 'phonegap']
         version {
-            name = '6.3.0-dev'
+            name = '6.3.0'
             released  = new Date()
-            vcsTag = '6.3.0-dev'
+            vcsTag = '6.3.0'
         }
     }
 }
diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java
index ec5bcc7..1f40e0f 100644
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -31,7 +31,7 @@ import android.webkit.WebChromeClient.CustomViewCallback;
  * are not expected to implement it.
  */
 public interface CordovaWebView {
-    public static final String CORDOVA_VERSION = "6.3.0-dev";
+    public static final String CORDOVA_VERSION = "6.3.0";
 
     void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);
 

-- 
To stop receiving notification emails like this one, please contact
"commits@cordova.apache.org" <co...@cordova.apache.org>.

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org