You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ra...@apache.org on 2021/07/14 08:25:40 UTC

[cordova-android] branch master updated: build: build cordova.js during npm prepare (#1271)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 35f0d07  build: build cordova.js during npm prepare (#1271)
35f0d07 is described below

commit 35f0d075219087685e159f0daaeacd512119cb25
Author: Raphael von der GrĂ¼n <ra...@gmail.com>
AuthorDate: Wed Jul 14 10:25:34 2021 +0200

    build: build cordova.js during npm prepare (#1271)
---
 .gitignore                                       |    3 +
 .npmignore                                       |    1 +
 lib/create.js                                    |    4 -
 package-lock.json                                |   81 +
 package.json                                     |    2 +
 templates/project/assets/www/cordova.js          | 1904 -------------------
 test/androidx/app/src/main/assets/www/cordova.js | 2206 ----------------------
 test/run_java_unit_tests.js                      |    5 +
 8 files changed, 92 insertions(+), 4114 deletions(-)

diff --git a/.gitignore b/.gitignore
index ae182f8..2e8cc1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,9 @@ example
 /framework/libs
 /framework/javadoc-public
 /framework/javadoc-private
+
+**/assets/www/cordova.js
+
 /test/.externalNativeBuild
 
 /test/androidx/gradle
diff --git a/.npmignore b/.npmignore
index 464d118..9fdc54d 100644
--- a/.npmignore
+++ b/.npmignore
@@ -3,3 +3,4 @@ coverage
 test
 spec
 framework/build
+cordova-js-src
diff --git a/lib/create.js b/lib/create.js
index 8b9a61e..2818264 100755
--- a/lib/create.js
+++ b/lib/create.js
@@ -56,10 +56,6 @@ function copyJsAndLibrary (projectPath, shared, projectName, targetAPI) {
     fs.ensureDirSync(platform_www);
     fs.copySync(srcCordovaJsPath, path.join(platform_www, 'cordova.js'));
 
-    // Copy cordova-js-src directory into platform_www directory.
-    // We need these files to build cordova.js if using browserify method.
-    fs.copySync(path.join(ROOT, 'cordova-js-src'), path.join(platform_www, 'cordova-js-src'));
-
     if (shared) {
         var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
         fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
diff --git a/package-lock.json b/package-lock.json
index d7af713..6b1ca49 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -520,6 +520,12 @@
         "is-string": "^1.0.5"
       }
     },
+    "array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
+    },
     "array.prototype.flat": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz",
@@ -774,6 +780,36 @@
         "underscore": "^1.9.2"
       }
     },
+    "cordova-js": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/cordova-js/-/cordova-js-6.1.0.tgz",
+      "integrity": "sha512-roVQ3qw0CISeM6E1AjQN+QkuiXoBDiVU2Xf9RXtwXSpT1QMtzS6Zz5+lj/f8pUfBr52zDj7lyV1crghMMjrNqg==",
+      "dev": true,
+      "requires": {
+        "execa": "^5.1.1",
+        "fs-extra": "^9.1.0",
+        "globby": "^11.0.4"
+      },
+      "dependencies": {
+        "execa": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+          "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^7.0.3",
+            "get-stream": "^6.0.0",
+            "human-signals": "^2.1.0",
+            "is-stream": "^2.0.0",
+            "merge-stream": "^2.0.0",
+            "npm-run-path": "^4.0.1",
+            "onetime": "^5.1.2",
+            "signal-exit": "^3.0.3",
+            "strip-final-newline": "^2.0.0"
+          }
+        }
+      }
+    },
     "cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -828,6 +864,23 @@
         "object-keys": "^1.0.12"
       }
     },
+    "dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "requires": {
+        "path-type": "^4.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+          "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+          "dev": true
+        }
+      }
+    },
     "doctrine": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -1606,6 +1659,28 @@
         "type-fest": "^0.8.1"
       }
     },
+    "globby": {
+      "version": "11.0.4",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
+      "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
+      "dev": true,
+      "requires": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.1.1",
+        "ignore": "^5.1.4",
+        "merge2": "^1.3.0",
+        "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "ignore": {
+          "version": "5.1.8",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+          "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+          "dev": true
+        }
+      }
+    },
     "graceful-fs": {
       "version": "4.2.6",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@@ -2870,6 +2945,12 @@
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
     },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true
+    },
     "slice-ansi": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
diff --git a/package.json b/package.json
index 663ca05..f3843bf 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "apache"
   ],
   "scripts": {
+    "prepare": "cordova-js build > templates/project/assets/www/cordova.js",
     "test": "npm run lint && npm run cover && npm run java-unit-tests",
     "lint": "eslint lib spec test \"templates/cordova/**/!(*.*)\"",
     "unit-tests": "jasmine --config=spec/unit/jasmine.json",
@@ -36,6 +37,7 @@
   },
   "devDependencies": {
     "@cordova/eslint-config": "^3.0.0",
+    "cordova-js": "^6.1.0",
     "jasmine": "^3.7.0",
     "jasmine-spec-reporter": "^7.0.0",
     "nyc": "^15.1.0",
diff --git a/templates/project/assets/www/cordova.js b/templates/project/assets/www/cordova.js
deleted file mode 100644
index 227b446..0000000
--- a/templates/project/assets/www/cordova.js
+++ /dev/null
@@ -1,1904 +0,0 @@
-// Platform: android
-// cordova-js rel/6.0.0-10-g07379820
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- 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
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-;(function() {
-var PLATFORM_VERSION_BUILD_LABEL = '10.0.0-dev';
-// file: src/scripts/require.js
-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 resultantId = id;
-            // 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;
-    }
-
-    require = function (id) {
-        if (!modules[id]) {
-            throw new Error('module ' + id + ' not found');
-        } else if (id in inProgressModules) {
-            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
-            throw new Error('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;
-    };
-
-    define = function (id, factory) {
-        if (Object.prototype.hasOwnProperty.call(modules, id)) {
-            throw new Error('module ' + id + ' already defined');
-        }
-
-        modules[id] = {
-            id: id,
-            factory: factory
-        };
-    };
-
-    define.remove = function (id) {
-        delete modules[id];
-    };
-
-    define.moduleMap = modules;
-})();
-
-// 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 = {};
-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 (Object.prototype.hasOwnProperty.call(data, 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);
-            }
-        } 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);
-        }
-    },
-
-    /**
-     * 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;
-            cordova.fireWindowEvent('cordovacallbackerror', { message: msg, error: err });
-            throw err;
-        }
-    },
-
-    addConstructor: function (func) {
-        channel.onCordovaReady.subscribe(function () {
-            try {
-                func();
-            } catch (e) {
-                console.log('Failed to run constructor: ' + e);
-            }
-        });
-    }
-};
-
-module.exports = cordova;
-
-});
-
-// file: ../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.
- */
-
-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: ../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);
-    }
-};
-
-});
-
-// file: src/common/argscheck.js
-define("cordova/argscheck", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-var moduleExports = module.exports;
-
-var typeMap = {
-    A: 'Array',
-    D: 'Date',
-    N: 'Number',
-    S: 'String',
-    F: 'Function',
-    O: 'Object'
-};
-
-function extractParamName (callee, argIndex) {
-    return (/\(\s*([^)]*?)\s*\)/).exec(callee)[1].split(/\s*,\s*/)[argIndex];
-}
-
-/**
- * Checks the given arguments' types and throws if they are not as expected.
- *
- * `spec` is a string where each character stands for the required type of the
- * argument at the same position. In other words: the character at `spec[i]`
- * specifies the required type for `args[i]`. The characters in `spec` are the
- * first letter of the required type's name. The supported types are:
- *
- *     Array, Date, Number, String, Function, Object
- *
- * Lowercase characters specify arguments that must not be `null` or `undefined`
- * while uppercase characters allow those values to be passed.
- *
- * Finally, `*` can be used to allow any type at the corresponding position.
- *
- * @example
- * function foo (arr, opts) {
- *     // require `arr` to be an Array and `opts` an Object, null or undefined
- *     checkArgs('aO', 'my.package.foo', arguments);
- *     // ...
- * }
- * @param {String} spec - the type specification for `args` as described above
- * @param {String} functionName - full name of the callee.
- * Used in the error message
- * @param {Array|arguments} args - the arguments to be checked against `spec`
- * @param {Function} [opt_callee=args.callee] - the recipient of `args`.
- * Used to extract parameter names for the error message
- * @throws {TypeError} if args do not satisfy spec
- */
-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);
-    }
-}
-
-function getValue (value, defaultValue) {
-    return value === undefined ? defaultValue : value;
-}
-
-moduleExports.checkArgs = checkArgs;
-moduleExports.getValue = getValue;
-moduleExports.enableChecks = true;
-
-});
-
-// file: src/common/base64.js
-define("cordova/base64", function(require, exports, module) {
-
-var base64 = exports;
-
-base64.fromArrayBuffer = function (arrayBuffer) {
-    var array = new Uint8Array(arrayBuffer);
-    return uint8ToBase64(array);
-};
-
-base64.toArrayBuffer = function (str) {
-    var decodedStr = atob(str);
-    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.
- */
-
-var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-var b64_12bit;
-
-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;
-}
-
-});
-
-// file: src/common/builder.js
-define("cordova/builder", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-function each (objects, func, context) {
-    for (var prop in objects) {
-        if (Object.prototype.hasOwnProperty.call(objects, prop)) {
-            func.apply(context, [objects[prop], prop]);
-        }
-    }
-}
-
-function clobber (obj, key, value) {
-    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 {
-                        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];
-                }
-            }
-
-            if (obj.children) {
-                include(result, obj.children, clobber, merge);
-            }
-        } catch (e) {
-            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
-        }
-    });
-}
-
-/**
- * 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 (Object.prototype.hasOwnProperty.call(src, 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 {
-                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;
-
-});
-
-// 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.');
-            }
-            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();
-        }
-    }
-};
-
-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;
-    }
-
-    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();
-        }
-    }
-};
-
-/**
- * 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;
-    }
-
-    guid = handleEvent.observer_guid;
-    handler = this.handlers[guid];
-    if (handler) {
-        delete this.handlers[guid];
-        this.numHandlers--;
-        if (this.numHandlers === 0) {
-            this.onHasSubscribersChange && this.onHasSubscribersChange();
-        }
-    }
-};
-
-/**
- * Calls all functions subscribed to this channel.
- */
-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: ../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');
-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 };
-    }
-
-    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 () {
-    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
-    channel.onNativeReady.fire();
-};
-
-function pollOnceFromOnlineEvent () {
-    pollOnce(true);
-}
-
-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();
-    }
-}
-
-function pollingTimerFunc () {
-    if (pollEnabled) {
-        pollOnce();
-        setTimeout(pollingTimerFunc, 50);
-    }
-}
-
-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;
-};
-
-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));
-    }
-}
-
-// 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.
-        // eslint-disable-next-line no-eval
-        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));
-    }
-}
-
-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);
-        }
-    }
-}
-
-function popMessageFromQueue () {
-    var messageBatch = messagesFromNative.shift();
-    if (messageBatch === '*') {
-        return '*';
-    }
-
-    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;
-}
-
-module.exports = androidExec;
-
-});
-
-// file: src/common/exec/proxy.js
-define("cordova/exec/proxy", function(require, exports, module) {
-
-// internal map of proxy function
-var CommandProxyMap = {};
-
-module.exports = {
-
-    // 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;
-    },
-
-    get: function (service, action) {
-        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
-    }
-};
-
-});
-
-// file: src/common/init.js
-define("cordova/init", function(require, exports, module) {
-
-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 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);
-        }
-    }
-}
-
-window.setTimeout(function () {
-    if (channel.onDeviceReady.state !== 2) {
-        console.log('deviceready has not fired after 5 seconds.');
-        logUnfiredChannels(platformInitChannelsArray);
-        logUnfiredChannels(channel.deviceReadyChannelsArray);
-    }
-}, 5000);
-
-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);
-
-/**
- * Create all cordova objects once native side is ready.
- */
-channel.join(function () {
-    modulemapper.mapModules(window);
-
-    platform.initialize && platform.initialize();
-
-    // Fire event to notify that all objects are created
-    channel.onCordovaReady.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);
-}, platformInitChannelsArray);
-
-});
-
-// file: src/common/modulemapper.js
-define("cordova/modulemapper", function(require, exports, module) {
-
-var builder = require('cordova/builder');
-var moduleMap = define.moduleMap;
-var symbolList;
-var deprecationMap;
-
-exports.reset = function () {
-    symbolList = [];
-    deprecationMap = {};
-};
-
-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;
-    }
-}
-
-// 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);
-};
-
-exports.runs = function (moduleName) {
-    addEntry('r', moduleName, null);
-};
-
-function prepareNamespace (symbolPath, context) {
-    if (!symbolPath) {
-        return context;
-    }
-    return symbolPath.split('.').reduce(function (cur, part) {
-        return (cur[part] = cur[part] || {});
-    }, context);
-}
-
-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.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;
-};
-
-exports.reset();
-
-});
-
-// file: ../cordova-android/cordova-js-src/platform.js
-define("cordova/platform", function(require, exports, module) {
-
-// The last resume event that was received that had the result of a plugin call.
-var lastResumeEvent = null;
-
-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');
-
-        // Get the shared secret needed to use the bridge.
-        exec.init();
-
-        // 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]);
-        };
-
-        // Add hardware MENU and SEARCH button handlers
-        cordova.addDocumentEventHandler('menubutton');
-        cordova.addDocumentEventHandler('searchbutton');
-
-        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);
-
-            if (evt === 'resume' && lastResumeEvent) {
-                handler(lastResumeEvent);
-            }
-        };
-
-        // 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) {
-    // pause and resume are Android app life cycle events
-    case 'backbutton':
-    case 'menubutton':
-    case 'searchbutton':
-    case 'pause':
-    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;
-            }
-
-            // 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: ../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');
-
-// 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 {
-                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]);
-            }
-        }
-
-        // Finally, if runs is truthy we want to simply require() the module.
-        if (module.runs) {
-            modulemapper.runs(module.id);
-        }
-    }
-
-    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);
-    }
-}
-
-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);
-};
-
-});
-
-// file: src/common/urlutil.js
-define("cordova/urlutil", function(require, exports, module) {
-
-/**
- * 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;
-};
-
-});
-
-// file: src/common/utils.js
-define("cordova/utils", function(require, exports, module) {
-
-var utils = exports;
-
-/**
- * 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;
-
-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;
-    }
-
-    var retVal, i;
-
-    if (utils.isArray(obj)) {
-        retVal = [];
-        for (i = 0; i < obj.length; ++i) {
-            retVal.push(utils.clone(obj[i]));
-        }
-        return retVal;
-    }
-
-    retVal = {};
-    for (i in obj) {
-        // 'unknown' type may be returned in custom protocol activation case on
-        // Windows Phone 8.1 causing "No such interface supported" exception on
-        // cloning (https://issues.apache.org/jira/browse/CB-11522)
-        // eslint-disable-next-line valid-typeof
-        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);
-    }
-};
-
-});
-
-window.cordova = require('cordova');
-// file: src/scripts/bootstrap.js
-require('cordova/init');
-
-})();
diff --git a/test/androidx/app/src/main/assets/www/cordova.js b/test/androidx/app/src/main/assets/www/cordova.js
deleted file mode 100644
index 11da9eb..0000000
--- a/test/androidx/app/src/main/assets/www/cordova.js
+++ /dev/null
@@ -1,2206 +0,0 @@
-// Platform: android
-// 7c5fcc5a5adfbf3fb8ceaf36fbdd4bd970bd9c20
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- 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
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-;(function() {
-var PLATFORM_VERSION_BUILD_LABEL = '6.2.0-dev';
-// file: src/scripts/require.js
-
-
-var require,
-    define;
-
-(function () {
-    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) === ".") {
-                    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;
-    }
-
-    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;
-    };
-
-    define = function (id, factory) {
-        if (modules[id]) {
-            throw "module " + id + " already defined";
-        }
-
-        modules[id] = {
-            id: id,
-            factory: factory
-        };
-    };
-
-    define.remove = function (id) {
-        delete modules[id];
-    };
-
-    define.moduleMap = modules;
-})();
-
-//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);
-    }
-};
-
-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);
-            }
-        } 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);
-        }
-    },
-
-    /**
-     * 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;
-        }
-    },
-    addConstructor: function(func) {
-        channel.onCordovaReady.subscribe(function() {
-            try {
-                func();
-            } catch(e) {
-                console.log("Failed to run constructor: " + e);
-            }
-        });
-    }
-};
-
-
-module.exports = cordova;
-
-});
-
-// file: /Users/steveng/repo/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.
- */
-
-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/steveng/repo/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);
-    }
-};
-
-});
-
-// file: src/common/argscheck.js
-define("cordova/argscheck", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-var moduleExports = module.exports;
-
-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 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;
-        }
-        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);
-    }
-}
-
-function getValue(value, defaultValue) {
-    return value === undefined ? defaultValue : value;
-}
-
-moduleExports.checkArgs = checkArgs;
-moduleExports.getValue = getValue;
-moduleExports.enableChecks = true;
-
-
-});
-
-// file: src/common/base64.js
-define("cordova/base64", function(require, exports, module) {
-
-var base64 = exports;
-
-base64.fromArrayBuffer = function(arrayBuffer) {
-    var array = new Uint8Array(arrayBuffer);
-    return uint8ToBase64(array);
-};
-
-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;
-};
-
-//------------------------------------------------------------------------------
-
-/* 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 b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-var b64_12bit;
-
-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;
-}
-
-});
-
-// file: src/common/builder.js
-define("cordova/builder", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-function each(objects, func, context) {
-    for (var prop in objects) {
-        if (objects.hasOwnProperty(prop)) {
-            func.apply(context, [objects[prop], 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 {
-                        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];
-                }
-            }
-
-            if (obj.children) {
-                include(result, obj.children, clobber, merge);
-            }
-        } catch(e) {
-            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
-        }
-    });
-}
-
-/**
- * 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 {
-                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 = {
-        /**
-         * 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,
-                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);
-        },
-
-        /**
-         * 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();
-            }
-        }
-    };
-
-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;
-    }
-
-    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();
-        }
-    }
-};
-
-/**
- * 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;
-    }
-
-    guid = handleEvent.observer_guid;
-    handler = this.handlers[guid];
-    if (handler) {
-        delete this.handlers[guid];
-        this.numHandlers--;
-        if (this.numHandlers === 0) {
-            this.onHasSubscribersChange && this.onHasSubscribersChange();
-        }
-    }
-};
-
-/**
- * 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]);
-        }
-        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/steveng/repo/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);
-    }
-
-    // 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++,
-        argsJson = JSON.stringify(args);
-    if (success || fail) {
-        cordova.callbacks[callbackId] = {success:success, fail:fail};
-    }
-
-    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;
-    }
-
-    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
-    channel.onNativeReady.fire();
-};
-
-function pollOnceFromOnlineEvent() {
-    pollOnce(true);
-}
-
-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();
-    }
-}
-
-function pollingTimerFunc() {
-    if (pollEnabled) {
-        pollOnce();
-        setTimeout(pollingTimerFunc, 50);
-    }
-}
-
-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;
-};
-
-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));
-    }
-}
-
-// 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));
-    }
-}
-
-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);
-        }
-    }
-}
-
-function popMessageFromQueue() {
-    var messageBatch = messagesFromNative.shift();
-    if (messageBatch == '*') {
-        return '*';
-    }
-
-    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;
-}
-
-module.exports = androidExec;
-
-});
-
-// file: src/common/exec/proxy.js
-define("cordova/exec/proxy", function(require, exports, module) {
-
-
-// internal map of proxy function
-var CommandProxyMap = {};
-
-module.exports = {
-
-    // 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;
-    },
-
-    get:function(service,action) {
-        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
-    }
-};
-});
-
-// file: src/common/init.js
-define("cordova/init", function(require, exports, module) {
-
-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');
-
-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);
-        }
-    }
-}
-
-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();
-}
-
-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);
-
-/**
- * Create all cordova objects once native side is ready.
- */
-channel.join(function() {
-    modulemapper.mapModules(window);
-
-    platform.initialize && platform.initialize();
-
-    // Fire event to notify that all objects are created
-    channel.onCordovaReady.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);
-
-}, platformInitChannelsArray);
-
-
-});
-
-// file: src/common/init_b.js
-define("cordova/init_b", function(require, exports, module) {
-
-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');
-
-var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
-
-// setting exec
-cordova.exec = require('cordova/exec');
-
-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);
-
-/**
- * Create all cordova objects once native side is ready.
- */
-channel.join(function() {
-    modulemapper.mapModules(window);
-
-    platform.initialize && platform.initialize();
-
-    // Fire event to notify that all objects are created
-    channel.onCordovaReady.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);
-
-}, platformInitChannelsArray);
-
-});
-
-// file: src/common/modulemapper.js
-define("cordova/modulemapper", function(require, exports, module) {
-
-var builder = require('cordova/builder'),
-    moduleMap = define.moduleMap,
-    symbolList,
-    deprecationMap;
-
-exports.reset = function() {
-    symbolList = [];
-    deprecationMap = {};
-};
-
-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;
-    }
-}
-
-// 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);
-};
-
-exports.runs = function(moduleName) {
-    addEntry('r', moduleName, 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);
-        }
-    }
-};
-
-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;
-};
-
-exports.reset();
-
-
-});
-
-// file: src/common/modulemapper_b.js
-define("cordova/modulemapper_b", function(require, exports, module) {
-
-var builder = require('cordova/builder'),
-    symbolList = [],
-    deprecationMap;
-
-exports.reset = function() {
-    symbolList = [];
-    deprecationMap = {};
-};
-
-function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
-    symbolList.push(strategy, moduleName, symbolPath);
-    if (opt_deprecationMessage) {
-        deprecationMap[symbolPath] = opt_deprecationMessage;
-    }
-}
-
-// 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);
-};
-
-exports.runs = function(moduleName) {
-    addEntry('r', moduleName, 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);
-        }
-    }
-};
-
-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;
-};
-
-exports.reset();
-
-
-});
-
-// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/platform.js
-define("cordova/platform", function(require, exports, module) {
-
-// The last resume event that was received that had the result of a plugin call.
-var lastResumeEvent = null;
-
-module.exports = {
-    id: 'android',
-    bootstrap: function() {
-        var channel = require('cordova/channel'),
-            cordova = require('cordova'),
-            exec = require('cordova/exec'),
-            modulemapper = require('cordova/modulemapper');
-
-        // Get the shared secret needed to use the bridge.
-        exec.init();
-
-        // 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]);
-        };
-
-        // Add hardware MENU and SEARCH button handlers
-        cordova.addDocumentEventHandler('menubutton');
-        cordova.addDocumentEventHandler('searchbutton');
-
-        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);
-
-            if (evt === 'resume' && lastResumeEvent) {
-                handler(lastResumeEvent);
-            }
-        };
-
-        // 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;
-                }
-
-                // 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/steveng/repo/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 {
-                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]);
-            }
-        }
-
-        // Finally, if runs is truthy we want to simply require() the module.
-        if (module.runs) {
-            modulemapper.runs(module.id);
-        }
-    }
-
-    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);
-    }
-}
-
-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);
-};
-
-
-});
-
-// file: src/common/pluginloader_b.js
-define("cordova/pluginloader_b", function(require, exports, module) {
-
-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]);
-            }
-        }
-
-        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);
-        }
-    }
-}
-
-// 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();
-};
-
-
-});
-
-// file: src/common/urlutil.js
-define("cordova/urlutil", function(require, exports, module) {
-
-
-/**
- * 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;
-};
-
-
-});
-
-// file: src/common/utils.js
-define("cordova/utils", function(require, exports, module) {
-
-var utils = exports;
-
-/**
- * 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;
-
-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;
-    }
-
-    var retVal, i;
-
-    if(utils.isArray(obj)){
-        retVal = [];
-        for(i = 0; i < obj.length; ++i){
-            retVal.push(utils.clone(obj[i]));
-        }
-        return retVal;
-    }
-
-    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);
-    }
-};
-
-
-
-
-
-});
-
-window.cordova = require('cordova');
-// file: src/scripts/bootstrap.js
-
-require('cordova/init');
-
-})();
\ No newline at end of file
diff --git a/test/run_java_unit_tests.js b/test/run_java_unit_tests.js
index 4657690..ba41e3a 100644
--- a/test/run_java_unit_tests.js
+++ b/test/run_java_unit_tests.js
@@ -50,7 +50,12 @@ class AndroidTestRunner {
         return Promise.resolve()
             .then(_ => console.log(`[${this.testTitle}] Preparing Gradle wrapper for Java unit tests.`))
             .then(_ => {
+                // TODO we should probably not only copy these files, but instead create a new project from scratch
                 fs.copyFileSync(path.resolve(this.projectDir, '../../framework/cdv-gradle-config-defaults.json'), path.resolve(this.projectDir, 'cdv-gradle-config.json'));
+                fs.copyFileSync(
+                    path.join(__dirname, '../templates/project/assets/www/cordova.js'),
+                    path.join(this.projectDir, 'app/src/main/assets/www/cordova.js')
+                );
             })
             .then(_ => this._createProjectBuilder())
             .then(_ => this._gradlew('--version'))

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