cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject [1/7] 3.0
Date Mon, 18 Nov 2013 23:40:41 GMT
Updated Branches:
  refs/heads/master a166f99a6 -> e077f68e3


http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/common/pluginloader.js
----------------------------------------------------------------------
diff --git a/src/js/common/pluginloader.js b/src/js/common/pluginloader.js
new file mode 100644
index 0000000..3da3b62
--- /dev/null
+++ b/src/js/common/pluginloader.js
@@ -0,0 +1,119 @@
+define("cordova/pluginloader", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+function injectScript(url, onload, onerror) {
+    var script = document.createElement("script");
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    script.onerror = onerror || onload;
+    script.src = url;
+    document.head.appendChild(script);
+}
+
+function onScriptLoadingComplete(moduleList) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) {
+        if (module) {
+            try {
+                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.
+                // This can be skipped if it had any merges or clobbers, though,
+                // since the mapper will already have required the module.
+                if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) {
+                    modulemapper.runs(module.id);
+                }
+            }
+            catch(err) {
+                // error with module, most likely clobbers, should we continue?
+            }
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Called when:
+// * There are plugins defined and all plugins are finished loading.
+// * There are no plugins to load.
+function finishPluginLoading() {
+    channel.onPluginsReady.fire();
+}
+
+// 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) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        onScriptLoadingComplete();
+        return;
+    }
+    function scriptLoadedCallback() {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectScript(path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function injectPluginScript(pathPrefix) {
+    injectScript(pathPrefix + 'cordova_plugins.js', function(){
+        try {
+            var moduleList = require("cordova/plugin_list");
+            handlePluginsObject(pathPrefix, moduleList);
+        } catch (e) {
+            // Error loading cordova_plugins.js, file not found or something
+            // this is an acceptable error, pre-3.0.0, so we just move on.
+            finishPluginLoading();
+        }
+    },finishPluginLoading); // also, add script load error handler for file not found
+}
+
+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;
+        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() {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectPluginScript(pathPrefix);
+};
+
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/common/symbols.js
----------------------------------------------------------------------
diff --git a/src/js/common/symbols.js b/src/js/common/symbols.js
new file mode 100644
index 0000000..6083a5f
--- /dev/null
+++ b/src/js/common/symbols.js
@@ -0,0 +1,11 @@
+define("cordova/symbols", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Use merges here in case others symbols files depend on this running first,
+// but fail to declare the dependency with a require().
+modulemapper.merges('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/common/utils.js
----------------------------------------------------------------------
diff --git a/src/js/common/utils.js b/src/js/common/utils.js
new file mode 100644
index 0000000..b157769
--- /dev/null
+++ b/src/js/common/utils.js
@@ -0,0 +1,168 @@
+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 = function(a) {
+    return utils.typeName(a) == 'Array';
+};
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function(d) {
+    return utils.typeName(d) == '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){
+        if(!(i in retVal) || retVal[i] != obj[i]) {
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function(context, func, params) {
+    if (typeof params == 'undefined') {
+        return function() {
+            return func.apply(context, arguments);
+        };
+    } else {
+        return function() {
+            return func.apply(context, params);
+        };
+    }
+};
+
+/**
+ * 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);
+    }
+};
+
+
+//------------------------------------------------------------------------------
+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;
+}
+
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/cordova.js
----------------------------------------------------------------------
diff --git a/src/js/cordova.js b/src/js/cordova.js
new file mode 100644
index 0000000..67cab53
--- /dev/null
+++ b/src/js/cordova.js
@@ -0,0 +1,251 @@
+/*
+ *  Licensed 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.
+ */
+
+define("cordova", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+
+/**
+ * Listen for DOMContentLoaded and notify our channel subscribers.
+ */
+document.addEventListener('DOMContentLoaded', function() {
+    channel.onDOMContentLoaded.fire();
+}, false);
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+    channel.onDOMContentLoaded.fire();
+}
+
+/**
+ * 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;
+}
+
+if(typeof window.console === "undefined") {
+    window.console = {
+        log:function(){}
+    };
+}
+// there are places in the framework where we call `warn` also, so we should make sure it exists
+if(typeof window.console.warn === "undefined") {
+    window.console.warn = function(msg) {
+        this.log("warn: " + msg);
+    }
+}
+
+var cordova = {
+    define:define,
+    require:require,
+    /**
+     * 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) {
+        try {
+            cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+        } catch (e) {
+            console.log("Error in error callback: " + callbackId + " = "+e);
+        }
+    },
+
+    /**
+     * 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.
+        try {
+            cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+        } catch (e) {
+            console.log("Error in error callback: " + callbackId + " = "+e);
+        }
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function(callbackId, success, status, args, keepCallback) {
+        var callback = cordova.callbacks[callbackId];
+        if (callback) {
+            if (success && status == cordova.callbackStatus.OK) {
+                callback.success && callback.success.apply(null, args);
+            } else if (!success) {
+                callback.fail && callback.fail.apply(null, args);
+            }
+
+            // Clear callback if not expecting any more results
+            if (!keepCallback) {
+                delete cordova.callbacks[callbackId];
+            }
+        }
+    },
+    addConstructor: function(func) {
+        channel.onCordovaReady.subscribe(function() {
+            try {
+                func();
+            } catch(e) {
+                console.log("Failed to run constructor: " + e);
+            }
+        });
+    }
+};
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+module.exports = cordova;
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/exec.js
----------------------------------------------------------------------
diff --git a/src/js/exec.js b/src/js/exec.js
new file mode 100644
index 0000000..69eed3e
--- /dev/null
+++ b/src/js/exec.js
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed 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.
+ *
+*/
+define("cordova/exec", function(require, exports, module) {
+var cordova = require('cordova'),
+    utils = require('cordova/utils');
+
+var callbackId = 1;
+cordova.callbacks = [];
+//FIXME: switch
+cordova.callback = function() {
+    var scId = arguments[0];
+    var callbackRef = null;
+
+    var parameters = [];
+    for (var i = 1; i < arguments.length; i++) {
+        parameters[i-1] = arguments[i];
+    }
+    callbackRef = cordova.callbacks[scId];
+
+    // Even IDs are success-, odd are error-callbacks - make sure we remove both
+    if ((scId % 2) !== 0) {
+        scId = scId - 1;
+    }
+    // Remove both the success as well as the error callback from the stack
+    delete cordova.callbacks[scId];
+    delete cordova.callbacks[scId + 1];
+
+    if (typeof callbackRef == "function") callbackRef.apply(this, parameters);
+};
+
+cordova.callbackWithoutRemove = function() {
+    var scId = arguments[0];
+    var callbackRef = null;
+
+    var parameters = [];
+    for (var i = 1; i < arguments.length; i++) {
+        parameters[i-1] = arguments[i];
+    }
+    callbackRef = cordova.callbacks[scId];
+
+    if (typeof(callbackRef) == "function") callbackRef.apply(this, parameters);
+};
+
+function ubuntuExec(success, fail, service, action, args) {
+    if (callbackId % 2) {
+        callbackId++;
+    }
+
+    var scId = callbackId++;
+    var ecId = callbackId++;
+    cordova.callbacks[scId] = success;
+    cordova.callbacks[ecId] = fail;
+
+    args.unshift(ecId);
+    args.unshift(scId);
+
+    navigator.qt.postMessage(JSON.stringify({messageType: "callPluginFunction", plugin: service, func: action, params: args}))
+}
+module.exports = ubuntuExec;
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/platform.js
----------------------------------------------------------------------
diff --git a/src/js/platform.js b/src/js/platform.js
new file mode 100644
index 0000000..19e9f6b
--- /dev/null
+++ b/src/js/platform.js
@@ -0,0 +1,35 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed 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.
+ *
+*/
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+    id: "ubuntu",
+    initialize:function() {
+        var channel = require("cordova/channel"),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
+
+        modulemapper.loadMatchingModules(/cordova.*\/symbols$/);
+
+        modulemapper.mapModules(window);
+    }
+};
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/js/require.js
----------------------------------------------------------------------
diff --git a/src/js/require.js b/src/js/require.js
new file mode 100644
index 0000000..aaf8eef
--- /dev/null
+++ b/src/js/require.js
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed 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.
+ *
+*/
+
+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 = {},
+        SEPERATOR = ".";
+
+
+
+    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(SEPERATOR)) + SEPERATOR + 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;
+}

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/qmlplugin.cpp
----------------------------------------------------------------------
diff --git a/src/qmlplugin.cpp b/src/qmlplugin.cpp
new file mode 100644
index 0000000..b02acfe
--- /dev/null
+++ b/src/qmlplugin.cpp
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed 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.
+ *
+*/
+#include "qmlplugin.h"
+#include "cordova.h"
+#include <QtCore>
+#include <qqml.h>
+
+void CordovaUbuntuPlugin::registerTypes(const char *) {
+    qmlRegisterType<CordovaWrapper>("CordovaUbuntu", CORDOVA_UBUNTU_MAJOR_VERSION, CORDOVA_UBUNTU_MINOR_VERSION, "Cordova");
+}

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/src/qmlplugin.h
----------------------------------------------------------------------
diff --git a/src/qmlplugin.h b/src/qmlplugin.h
new file mode 100644
index 0000000..4e53189
--- /dev/null
+++ b/src/qmlplugin.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed 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.
+ *
+*/
+#ifndef QMLPLUGIN_H_SDASDAS
+#define QMLPLUGIN_H_SDASDAS
+
+#include <QtCore>
+#include <QtQuick>
+#include <cassert>
+
+#include "cordova.h"
+
+class CordovaWrapper: public QQuickItem {
+    Q_OBJECT
+    Q_PROPERTY(QString wwwDir READ wwwDir WRITE setWwwDir SCRIPTABLE true FINAL)
+    Q_PROPERTY(QString mainUrl READ mainUrl CONSTANT)
+public:
+    CordovaWrapper() = default;
+
+    QString wwwDir() {
+        if (!m_cordova.data()) {
+            return "";
+        }
+        return m_wwwDir;
+    }
+
+    void setWwwDir(const QString &www) {
+        assert(!m_cordova.data());
+        m_cordova = QSharedPointer<Cordova>(new Cordova(QDir(www), this));
+        m_wwwDir = www;
+
+        connect(m_cordova.data(), &Cordova::javaScriptExecNeeded, [&] (const QString &js) {
+            emit javaScriptExecNeeded(js);
+        });
+        connect(m_cordova.data(), &Cordova::qmlExecNeeded, [&] (const QString &src) {
+            emit qmlExecNeeded(src);
+        });
+        connect(m_cordova.data(), &Cordova::pluginWantsToBeAdded, [&] (const QString &pluginName, QObject *pluginObject, const QString &pluginShortName) {
+            emit pluginWantsToBeAdded(pluginName, pluginObject, pluginShortName);
+        });
+    }
+
+    Q_INVOKABLE static QString getSplashscreenPath(QQuickItem *parent, const QString &www) {
+        return QSharedPointer<Cordova>(new Cordova(QDir(www), parent))->getSplashscreenPath();
+    }
+
+    QString mainUrl() {
+        if (!m_cordova.data()) {
+            return "";
+        }
+        return m_cordova->mainUrl();
+    }
+
+signals:
+    void javaScriptExecNeeded(const QString &js);
+    void pluginWantsToBeAdded(const QString &pluginName, QObject *pluginObject, const QString &pluginShortName);
+    void qmlExecNeeded(const QString &src);
+public slots:
+    void setTitle(const QString &title) {
+        if (!m_cordova.data() || !m_cordova->rootObject()) {
+            return;
+        }
+        return m_cordova->setTitle(title);
+    }
+
+    void loadFinished(bool b) {
+        if (!m_cordova.data()) {
+            return;
+        }
+        return m_cordova->loadFinished(b);
+    }
+
+private:
+    QSharedPointer<Cordova> m_cordova;
+    QString m_wwwDir;
+};
+
+class CordovaUbuntuPlugin: public QQmlExtensionPlugin {
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+    void registerTypes(const char *uri);
+};
+
+#endif

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/www/basic.js
----------------------------------------------------------------------
diff --git a/www/basic.js b/www/basic.js
new file mode 100644
index 0000000..6cc6d60
--- /dev/null
+++ b/www/basic.js
@@ -0,0 +1,294 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+var vibration_length = 1000;
+
+function get(id) {
+    return document.getElementById(id);
+}
+
+function init() {
+    navigator.accelerometer.watchAcceleration(function (v) {
+        get("accel_val").innerHTML = v.x + '   ' + v.y + '    ' + v.z;
+    }, null, {frequency:100});
+}
+
+function getCurrentConnectionType() {
+    var networkState = navigator.network.connection.type;
+
+    var states = {};
+    states[Connection.UNKNOWN]  = 'Unknown connection';
+    states[Connection.ETHERNET] = 'Ethernet connection';
+    states[Connection.WIFI]     = 'WiFi connection';
+    states[Connection.CELL_2G]  = 'Cell 2G connection';
+    states[Connection.CELL_3G]  = 'Cell 3G connection';
+    states[Connection.CELL_4G]  = 'Cell 4G connection';
+    states[Connection.NONE]     = 'No network connection';
+    get("debug_output").innerHTML = states[networkState]
+    console.log("network state = " + states[networkState])
+}
+
+function test_vibra() {
+    navigator.notification.vibrate(vibration_length);
+    navigator.notification.beep(5);
+}
+
+function test_alert_confirm() {
+    navigator.notification.alert("This is an alert.", function alertDismissed() {}, "title", "buttonName");
+    navigator.notification.confirm("This is a confirm.", function onConfirm(button) {
+        if (button === 1) {
+            alert('User input: YES');
+        } else if (button === 2) {alert('User input: No');}
+    }, "title", "buttonName");
+}
+
+
+function getCurrentPosition() {
+    navigator.geolocation.getCurrentPosition(function(position) {
+        //                                                 get("position_val").innerHTML = position.coords.latitude + " / " + position.coords.longitude;
+        get("position_val").innerHTML = " success ";
+    },
+    function(error) {
+        get("position_val").innerHTML = "error";
+    }, { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true });
+}
+
+function getCurrentHeading() {
+    navigator.compass.getCurrentHeading(function(heading) {
+        get("heading_val").innerHTML = heading.magneticHeading;
+    },
+    function(error) {
+        get("heading_val").innerHTML = error.code + ": "  + error.message;
+    },
+    {timestamp: (new Date()).getTime()});
+}
+
+function getCurrentAcceleration() {
+    navigator.accelerometer.getCurrentAcceleration(function (acceleration) {
+        get("accel_val").innerHTML = acceleration.x + ' ' + acceleration.y + ' ' + acceleration.z;
+    }, function() {
+        get("accel_val").innerHTML = "accelerometer is not avaliable";
+    });
+}
+
+function getPicture(){
+    navigator.camera.getPicture(function(picture_file){
+        console.log("getPicture succeed callback: "+picture_file)
+        get("picture_val").innerHTML = '<img width="200" src="' + picture_file +'" />';
+    },
+    function(){
+        console.log("getPicture error callback")
+        get("picture_val").innerHTML = 'Capture cancelled or error occured'
+    },
+    { quality : 75,
+        destinationType : Camera.DestinationType.FILE_URI,
+        sourceType : Camera.PictureSourceType.CAMERA,
+        allowEdit : true,
+        encodingType: Camera.EncodingType.JPEG,
+        targetWidth: 100,
+        targetHeight: 100});
+}
+
+
+function test_requestFileSystem() {
+    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(p_fileSystem) {
+        get("debug_output").innerHTML = p_fileSystem.name + " / " + p_fileSystem.root.fullPath;
+
+
+        p_fileSystem.root.getFile("test.txt", { create: true, exclusive: false }, function(p_fileEntry) {
+            p_fileEntry.file(function(p_file) {
+                var fileReader = new FileReader();
+                fileReader.readAsText(p_file);
+            }, fileError);
+        }, fileError);
+    }, function() {});
+}
+
+function fileError(p_fileError) {
+    get("debug_output").innerHTML = p_filerError.code;
+}
+
+
+function createTestContact() {
+    var created = navigator.contacts.create({"name": {familyName: "Family", givenName: "Given"}, phoneNumbers: [{"value": "+123456789", pref: false, type: "work"}], emails: [{"value": "given.family@gmail.com", pref: false, type: "email"}, {"value": "given@family.com", pref: false, type: "email"}], birthday: new Date(1985, 4, 3, 0, 0, 0)})
+    created.save(function() {
+        get("create_contact_result").innerHTML = "Contact created"
+    }, function(error) {
+        get("create_contact_result").innerHTML = "Error occured: " + error;
+    })
+}
+
+function searchForTestContact() {
+    navigator.contacts.find(["name", "phoneNumbers", "nickname", "displayName", "emails", "ims", "addresses", "organizations", "birthday", "photos"], function(contacts) {
+        var result = ""
+        for (var contact in contacts) {
+            result += contacts[contact].name.formatted + ": " + contacts[contact].phoneNumbers[0].value + ", " + contacts[contact].emails[0].value + "<br />"
+        }
+        get("search_contact_result").innerHTML = result
+    }, function(error) {
+        get("search_contact_result").innerHTML = "Error occured: " + error
+    }, {filter:"Given", multiple: true});
+}
+
+
+function removeTestContact() {
+    get("remove_contact_result").innerHTML = ""
+    navigator.contacts.find(["name"],
+                            function(contacts){
+                                for (var contact in contacts) {
+                                    contacts[contact].remove(function() {
+                                        get("remove_contact_result").innerHTML += "Contact removed; "
+                                    },
+                                    function(error) {
+                                        get("remove_contact_result").innerHTML += "Error occured: " + error + "; "
+                                    })
+                                }
+                            },
+                            0, {filter:"Given", multiple: true})
+}
+
+var media = null;
+function mediaOpen(){
+    console.log("opened media file...");
+    media = new Media("testFile.mp3");
+    console.log("finished media file");
+    var position=0;
+    var duration=0;
+
+    var mediaTimer = setInterval(function() {
+        duration = media.getDuration();
+        media.getCurrentPosition(function (pos) {
+            position = pos;
+        });
+        get("media_position_duration_val").innerHTML = position + " / " + duration;
+    }, 1000);
+}
+
+function mediaPlay(){
+    media.play();
+}
+function mediaPause(){
+    media.pause();
+}
+function mediaStop(){
+    media.stop();
+}
+function mediaStartRecording() {
+    media.startRecord();
+}
+function mediaStopRecording() {
+    media.stopRecord();
+}
+function mediaFF5sec(){
+    media.getCurrentPosition(function (position) {
+        var jumpPosition = position * 1000 + 5000;
+        if (jumpPosition < media.getDuration() * 1000)
+            media.seekTo(jumpPosition);
+    });
+}
+
+function captureImage() {
+    navigator.device.capture.captureImage(function (mediaFiles) {
+        var res = "";
+        for (var i = 0; i < mediaFiles.length; i++) {
+            res += '<img src="file://' + mediaFiles[i].fullPath + '"></img>';
+        }
+        get("pics").innerHTML = res;
+    }, function() {
+        get("pics").innerHTML = "error";
+    }, { limit: 2 });
+}
+
+function captureAudio() {
+    navigator.device.capture.captureAudio(function (mediaFiles) {
+        var res = "";
+        for (var i = 0; i < mediaFiles.length; i++) {
+            res += "<audio controls>";
+            res += "<source src='file://" + mediaFiles[i].fullPath + "'>";
+            res += "</audio>";
+        }
+        get("audio").innerHTML = res;
+    }, function() {
+        get("audio").innerHTML = "error";
+    }, { limit: 2, mode: "audio/wav" });
+}
+
+function recordVideo() {
+    navigator.device.capture.captureVideo(function (mediaFiles) {
+        var res = "";
+        for (var i = 0; i < mediaFiles.length; i++) {
+            res += '<video src="file://' + mediaFiles[i].fullPath + '" controls>' + i + '</video>';
+        }
+        get("videos").innerHTML = res;
+    }, function () {
+        get("videos").innerHTML = "error";
+    }, { limit: 2, duration: 10 });
+}
+
+document.addEventListener("deviceready", function() {
+    console.log("basicjs.deviceReady")
+    get("debug_output").innerHTML = "Device Ready!<br/>";
+}, false);
+
+document.addEventListener("resume", function() {
+    console.log("basicjs.resume")
+}, false);
+
+document.addEventListener("pause", function() {
+    console.log("basicjs.pause")
+}, false);
+
+document.addEventListener("offline", function() {
+    console.log("basicjs.offline")
+    get("debug_output").innerHTML += "We are offline :(<br/>";
+}, false);
+
+document.addEventListener("online", function() {
+    console.log("basicjs.online")
+    get("debug_output").innerHTML += "We are online :)<br/>";
+}, false);
+
+
+document.addEventListener("batterycritical", function (info) {
+    console.log("basicjs.batteryCritical")
+    get("debug_output").innerHTML = "Battery Level Critical " + info.level + "%<br/>";
+}, false)
+
+
+document.addEventListener("batterylow", function (info) {
+    console.log("basicjs.batteryLow")
+    get("debug_output").innerHTML = "Battery Level Low " + info.level + "%<br/>";
+}, false)
+
+document.addEventListener("batterystatus", function (info) {
+    console.log("basicjs.batteryStatus")
+    get("debug_output").innerHTML = "Battery Level Changed " + info.level + "%<br/>";
+}, false)
+
+document.addEventListener("volumedownbutton", function () {
+    console.log("basicjs.volumeDownKeyPressed")
+    get("debug_output").innerHTML = "Volume Down Button<br/>";
+}, false)
+
+document.addEventListener("volumeupbutton", function () {
+    console.log("basicjs.volumeUpKeyPressed")
+    get("debug_output").innerHTML = "Volume Up Button<br/>";
+}, false)

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/www/index.html.in
----------------------------------------------------------------------
diff --git a/www/index.html.in b/www/index.html.in
new file mode 100644
index 0000000..89ac52c
--- /dev/null
+++ b/www/index.html.in
@@ -0,0 +1,90 @@
+<!--
+
+ 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.
+
+-->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>Cordova-Qt Test Page</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <script language="javascript" type="text/javascript" src="cordova-@VERSION@.js"></script>
+        <script language="javascript" type="text/javascript" src="basic.js"></script>
+
+        <style type="text/css">
+            input {
+                height: 60px;
+                margin-top: 15px;
+            }
+        </style>
+    </head>
+    <body>
+        <input type="button" value="CaptureAudio" onclick="captureAudio()"/>
+        <div id="audio"></div>
+        <br />
+        <input type="button" value="Capture" onclick="captureImage()"/>
+        <div id="pics"></div>
+        <br />
+        <input type="button" value="record video" onclick="recordVideo()"/>
+        <div id="videos"></div>
+        <br />
+        <input type="button" value="Init Watchers" onclick="init();"/>
+        <br />
+        <input type="button" value="Vibrate" onclick="test_vibra();"/>
+        <br />
+        <input type="button" value="Alert/Confirm" onclick="test_alert_confirm();">
+        <br />
+        <input type="button" value="Check Connection" onclick="getCurrentConnectionType();">
+        <br />
+        <input type="button" value="Request File System" onclick="test_requestFileSystem();">
+        <br />
+        <div id="debug_output"> </div>
+        <input type="button" value="Get Current Position" onclick="getCurrentPosition();">
+        <br />
+        <div id="position_val"> Location </div>
+        <input type="button" value="Get Acceleration" onclick="getCurrentAcceleration();">
+        <br />
+        <div id="accel_val"> Acceleration </div>
+        <input type="button" value="Get Current Heading" onclick="getCurrentHeading();">
+        <br />
+        <div id="heading_val"> Heading </div>
+        <input type="button" value="Get Picture" onclick="getPicture();">
+        <br />
+        <div id="picture_val"> Picture</div>
+        <input type="button" value="Create Test Contact" onclick="createTestContact();">
+        <br />
+        <div id="create_contact_result"></div>
+        <input type="button" value="Search for Test Contact" onclick="searchForTestContact();">
+        <br />
+        <div id="search_contact_result"></div>
+        <input type="button" value="Remove Test Contact" onclick="removeTestContact();">
+        <br />
+        <div id="remove_contact_result"></div>
+        <input type="button" value="Media Open" onclick="mediaOpen();">
+        <input type="button" value="Play" onclick="mediaPlay();">
+        <input type="button" value="Pause" onclick="mediaPause();">
+        <input type="button" value="Stop" onclick="mediaStop();">
+        <input type="button" value="Start Recording" onclick="mediaStartRecording();">
+        <input type="button" value="Stop Recording" onclick="mediaStopRecording();">
+        <input type="button" value="FF 5sec" onclick="mediaFF5sec();">
+        <br />
+        <div id="media_position_duration_val"> Position/Duration</div>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/www/plugins.xml
----------------------------------------------------------------------
diff --git a/www/plugins.xml b/www/plugins.xml
new file mode 100644
index 0000000..b06e46c
--- /dev/null
+++ b/www/plugins.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ 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.
+
+-->
+
+<plugins>
+    <plugin name="File" value="com.cordova.File"/>
+    <plugin name="Notification" value="com.cordova.Notification"/>
+    <plugin name="Accelerometer" value="com.cordova.Accelerometer"/>
+    <plugin name="Events" value="com.cordova.Events"/>
+    <plugin name="Geolocation" value="com.cordova.Geolocation"/>
+    <plugin name="Device" value="com.cordova.Device"/>
+    <plugin name="Console" value="com.cordova.Console"/>
+    <plugin name="Connection" value="com.cordova.Connection"/>
+    <plugin name="Compass" value="com.cordova.Compass"/>
+    <plugin name="Camera" value="com.cordova.Camera"/>
+    <plugin name="Contacts" value="com.cordova.Contacts"/>
+    <plugin name="Media" value="com.cordova.Media"/>
+    <plugin name="Globalization" value="com.cordova.Globalization"/>
+    <plugin name="Capture" value="com.cordova.Capture"/>
+    <plugin name="Splashscreen" value="com.cordova.Splashscreen"/>
+    <plugin name="InAppBrowser" value="com.cordova.InAppBrowser"/>
+
+<!-- Non standart -->
+    <plugin name="App" value="com.cordova.App"/>
+    <plugin name="EchoPlugin" value="com.example.echo"/>
+</plugins>

http://git-wip-us.apache.org/repos/asf/cordova-ubuntu/blob/b6c3aee7/xml/config.xml
----------------------------------------------------------------------
diff --git a/xml/config.xml b/xml/config.xml
new file mode 100644
index 0000000..50459b9
--- /dev/null
+++ b/xml/config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<widget xmlns     = "http://www.w3.org/ns/widgets"
+        id        = "io.cordova.helloCordova"
+        version   = "2.0.0">
+    <name>Hello Cordova</name>
+
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+
+    <author href="http://cordova.io" email="dev@cordova.apache.org">
+        Apache Cordova Team
+    </author>
+
+    <access origin="*"/>
+
+    <!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
+    <content src="index.html" />
+
+    <preference name="loglevel" value="DEBUG" />
+    <!--
+      <preference name="splashscreen" value="resourceName" />
+      <preference name="backgroundColor" value="0xFFF" />
+      <preference name="loadUrlTimeoutValue" value="20000" />
+      <preference name="InAppBrowserStorageEnabled" value="true" />
+      <preference name="disallowOverscroll" value="true" />
+    -->
+</widget>


Mime
View raw message