You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sg...@apache.org on 2015/09/20 14:18:00 UTC

[01/10] cordova-lib git commit: CB-9598 Initial implementation for cordova-common module

Repository: cordova-lib
Updated Branches:
  refs/heads/master 436679fd7 -> 1594c0afa


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/configparser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/configparser/ConfigParser.js b/cordova-common/src/configparser/ConfigParser.js
new file mode 100644
index 0000000..9dcccb5
--- /dev/null
+++ b/cordova-common/src/configparser/ConfigParser.js
@@ -0,0 +1,470 @@
+/**
+    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.
+*/
+
+/* jshint sub:true */
+
+var et = require('elementtree'),
+    xml= require('../util/xml-helpers'),
+    CordovaError = require('../CordovaError'),
+    fs = require('fs'),
+    events = require('../events');
+
+
+/** Wraps a config.xml file */
+function ConfigParser(path) {
+    this.path = path;
+    try {
+        this.doc = xml.parseElementtreeSync(path);
+        this.cdvNamespacePrefix = getCordovaNamespacePrefix(this.doc);
+        et.register_namespace(this.cdvNamespacePrefix, 'http://cordova.apache.org/ns/1.0');
+    } catch (e) {
+        console.error('Parsing '+path+' failed');
+        throw e;
+    }
+    var r = this.doc.getroot();
+    if (r.tag !== 'widget') {
+        throw new CordovaError(path + ' has incorrect root node name (expected "widget", was "' + r.tag + '")');
+    }
+}
+
+function getNodeTextSafe(el) {
+    return el && el.text && el.text.trim();
+}
+
+function findOrCreate(doc, name) {
+    var ret = doc.find(name);
+    if (!ret) {
+        ret = new et.Element(name);
+        doc.getroot().append(ret);
+    }
+    return ret;
+}
+
+function getCordovaNamespacePrefix(doc){
+    var rootAtribs = Object.getOwnPropertyNames(doc.getroot().attrib);
+    var prefix = 'cdv';
+    for (var j = 0; j < rootAtribs.length; j++ ) {
+        if(rootAtribs[j].indexOf('xmlns:') === 0 &&
+            doc.getroot().attrib[rootAtribs[j]] === 'http://cordova.apache.org/ns/1.0'){
+            var strings = rootAtribs[j].split(':');
+            prefix = strings[1];
+            break;
+        }
+    }
+    return prefix;
+}
+
+/**
+ * Finds the value of an element's attribute
+ * @param  {String} attributeName Name of the attribute to search for
+ * @param  {Array}  elems         An array of ElementTree nodes
+ * @return {String}
+ */
+function findElementAttributeValue(attributeName, elems) {
+
+    elems = Array.isArray(elems) ? elems : [ elems ];
+
+    var value = elems.filter(function (elem) {
+        return elem.attrib.name.toLowerCase() === attributeName.toLowerCase();
+    }).map(function (filteredElems) {
+        return filteredElems.attrib.value;
+    }).pop();
+
+    return value ? value : '';
+}
+
+ConfigParser.prototype = {
+    packageName: function(id) {
+        return this.doc.getroot().attrib['id'];
+    },
+    setPackageName: function(id) {
+        this.doc.getroot().attrib['id'] = id;
+    },
+    android_packageName: function() {
+        return this.doc.getroot().attrib['android-packageName'];
+    },
+    android_activityName: function() {
+	return this.doc.getroot().attrib['android-activityName'];
+    },
+    ios_CFBundleIdentifier: function() {
+        return this.doc.getroot().attrib['ios-CFBundleIdentifier'];
+    },
+    name: function() {
+        return getNodeTextSafe(this.doc.find('name'));
+    },
+    setName: function(name) {
+        var el = findOrCreate(this.doc, 'name');
+        el.text = name;
+    },
+    description: function() {
+        return getNodeTextSafe(this.doc.find('description'));
+    },
+    setDescription: function(text) {
+        var el = findOrCreate(this.doc, 'description');
+        el.text = text;
+    },
+    version: function() {
+        return this.doc.getroot().attrib['version'];
+    },
+    android_versionCode: function() {
+        return this.doc.getroot().attrib['android-versionCode'];
+    },
+    ios_CFBundleVersion: function() {
+        return this.doc.getroot().attrib['ios-CFBundleVersion'];
+    },
+    setVersion: function(value) {
+        this.doc.getroot().attrib['version'] = value;
+    },
+    author: function() {
+        return getNodeTextSafe(this.doc.find('author'));
+    },
+    getGlobalPreference: function (name) {
+        return findElementAttributeValue(name, this.doc.findall('preference'));
+    },
+    setGlobalPreference: function (name, value) {
+        var pref = this.doc.find('preference[@name="' + name + '"]');
+        if (!pref) {
+            pref = new et.Element('preference');
+            pref.attrib.name = name;
+            this.doc.getroot().append(pref);
+        }
+        pref.attrib.value = value;
+    },
+    getPlatformPreference: function (name, platform) {
+        return findElementAttributeValue(name, this.doc.findall('platform[@name=\'' + platform + '\']/preference'));
+    },
+    getPreference: function(name, platform) {
+
+        var platformPreference = '';
+
+        if (platform) {
+            platformPreference = this.getPlatformPreference(name, platform);
+        }
+
+        return platformPreference ? platformPreference : this.getGlobalPreference(name);
+
+    },
+    /**
+     * Returns all resources for the platform specified.
+     * @param  {String} platform     The platform.
+     * @param {string}  resourceName Type of static resources to return.
+     *                               "icon" and "splash" currently supported.
+     * @return {Array}               Resources for the platform specified.
+     */
+    getStaticResources: function(platform, resourceName) {
+        var ret = [],
+            staticResources = [];
+        if (platform) { // platform specific icons
+            this.doc.findall('platform[@name=\'' + platform + '\']/' + resourceName).forEach(function(elt){
+                elt.platform = platform; // mark as platform specific resource
+                staticResources.push(elt);
+            });
+        }
+        // root level resources
+        staticResources = staticResources.concat(this.doc.findall(resourceName));
+        // parse resource elements
+        var that = this;
+        staticResources.forEach(function (elt) {
+            var res = {};
+            res.src = elt.attrib.src;
+            res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix+':density'] || elt.attrib['gap:density'];
+            res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
+            res.width = +elt.attrib.width || undefined;
+            res.height = +elt.attrib.height || undefined;
+
+            // default icon
+            if (!res.width && !res.height && !res.density) {
+                ret.defaultResource = res;
+            }
+            ret.push(res);
+        });
+
+        /**
+         * Returns resource with specified width and/or height.
+         * @param  {number} width Width of resource.
+         * @param  {number} height Height of resource.
+         * @return {Resource} Resource object or null if not found.
+         */
+        ret.getBySize = function(width, height) {
+            return ret.filter(function(res) {
+                if (!res.width && !res.height) {
+                    return false;
+                }
+                return ((!res.width || (width == res.width)) &&
+                    (!res.height || (height == res.height)));
+            })[0] || null;
+        };
+
+        /**
+         * Returns resource with specified density.
+         * @param  {string} density Density of resource.
+         * @return {Resource}       Resource object or null if not found.
+         */
+        ret.getByDensity = function(density) {
+            return ret.filter(function(res) {
+                return res.density == density;
+            })[0] || null;
+        };
+
+        /** Returns default icons */
+        ret.getDefault = function() {
+            return ret.defaultResource;
+        };
+
+        return ret;
+    },
+
+    /**
+     * Returns all icons for specific platform.
+     * @param  {string} platform Platform name
+     * @return {Resource[]}      Array of icon objects.
+     */
+    getIcons: function(platform) {
+        return this.getStaticResources(platform, 'icon');
+    },
+
+    /**
+     * Returns all splash images for specific platform.
+     * @param  {string} platform Platform name
+     * @return {Resource[]}      Array of Splash objects.
+     */
+    getSplashScreens: function(platform) {
+        return this.getStaticResources(platform, 'splash');
+    },
+
+    /**
+     * Returns all hook scripts for the hook type specified.
+     * @param  {String} hook     The hook type.
+     * @param {Array}  platforms Platforms to look for scripts into (root scripts will be included as well).
+     * @return {Array}               Script elements.
+     */
+    getHookScripts: function(hook, platforms) {
+        var self = this;
+        var scriptElements = self.doc.findall('./hook');
+
+        if(platforms) {
+            platforms.forEach(function (platform) {
+                scriptElements = scriptElements.concat(self.doc.findall('./platform[@name="' + platform + '"]/hook'));
+            });
+        }
+
+        function filterScriptByHookType(el) {
+            return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
+        }
+
+        return scriptElements.filter(filterScriptByHookType);
+    },
+   /**
+    * Returns a list of plugin (IDs).
+    *
+    * This function also returns any plugin's that
+    * were defined using the legacy <feature> tags.
+    * @return {string[]} Array of plugin IDs
+    */
+    getPluginIdList: function () {
+        var plugins = this.doc.findall('plugin');
+        var result = plugins.map(function(plugin){
+            return plugin.attrib.name;
+        });
+        var features = this.doc.findall('feature');
+        features.forEach(function(element ){
+            var idTag = element.find('./param[@name="id"]');
+            if(idTag){
+                result.push(idTag.attrib.value);
+            }
+        });
+        return result;
+    },
+    getPlugins: function () {
+        return this.getPluginIdList().map(function (pluginId) {
+            return this.getPlugin(pluginId);
+        }, this);
+    },
+    /**
+     * Adds a plugin element. Does not check for duplicates.
+     * @name addPlugin
+     * @function
+     * @param {object} attributes name and spec are supported
+     * @param {Array|object} variables name, value or arbitary object
+     */
+    addPlugin: function (attributes, variables) {
+        if (!attributes && !attributes.name) return;
+        var el = new et.Element('plugin');
+        el.attrib.name = attributes.name;
+        if (attributes.spec) {
+            el.attrib.spec = attributes.spec;
+        }
+
+        // support arbitrary object as variables source
+        if (variables && typeof variables === 'object' && !Array.isArray(variables)) {
+            variables = Object.keys(variables)
+            .map(function (variableName) {
+                return {name: variableName, value: variables[variableName]};
+            });
+        }
+
+        if (variables) {
+            variables.forEach(function (variable) {
+                el.append(new et.Element('variable', { name: variable.name, value: variable.value }));
+            });
+        }
+        this.doc.getroot().append(el);
+    },
+    /**
+     * Retrives the plugin with the given id or null if not found.
+     *
+     * This function also returns any plugin's that
+     * were defined using the legacy <feature> tags.
+     * @name getPlugin
+     * @function
+     * @param {String} id
+     * @returns {object} plugin including any variables
+     */
+    getPlugin: function(id){
+        if(!id){
+            return undefined;
+        }
+        var pluginElement = this.doc.find('./plugin/[@name="' + id + '"]');
+        if (null === pluginElement) {
+            var legacyFeature =  this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
+            if(legacyFeature){
+                 events.emit('log', 'Found deprecated feature entry for ' + id +' in config.xml.');
+                return featureToPlugin(legacyFeature);
+            }
+            return undefined;
+        }
+        var plugin = {};
+
+        plugin.name = pluginElement.attrib.name;
+        plugin.spec = pluginElement.attrib.spec || pluginElement.attrib.src || pluginElement.attrib.version;
+        plugin.variables = {};
+        var variableElements = pluginElement.findall('variable');
+        variableElements.forEach(function(varElement){
+            var name = varElement.attrib.name;
+            var value = varElement.attrib.value;
+            if(name){
+                plugin.variables[name] = value;
+            }
+        });
+        return plugin;
+    },
+    /**
+     * Remove the plugin entry with give name (id).
+     *
+     * This function also operates on any plugin's that
+     * were defined using the legacy <feature> tags.
+     * @name removePlugin
+     * @function
+     * @param id name of the plugin
+     */
+    removePlugin: function(id){
+        if(id){
+            var plugins = this.doc.findall('./plugin/[@name="' + id + '"]')
+                .concat(this.doc.findall('./feature/param[@name="id"][@value="' + id + '"]/..'));
+            var children = this.doc.getroot().getchildren();
+            plugins.forEach(function (plugin) {
+                var idx = children.indexOf(plugin);
+                if (idx > -1) {
+                    children.splice(idx, 1);
+                }
+            });
+        }
+    },
+
+    // Add any element to the root
+    addElement: function(name, attributes) {
+        var el = et.Element(name);
+        for (var a in attributes) {
+            el.attrib[a] = attributes[a];
+        }
+        this.doc.getroot().append(el);
+    },
+
+    /**
+     * Adds an engine. Does not check for duplicates.
+     * @param  {String} name the engine name
+     * @param  {String} spec engine source location or version (optional)
+     */
+    addEngine: function(name, spec){
+        if(!name) return;
+        var el = et.Element('engine');
+        el.attrib.name = name;
+        if(spec){
+            el.attrib.spec = spec;
+        }
+        this.doc.getroot().append(el);
+    },
+    /**
+     * Removes all the engines with given name
+     * @param  {String} name the engine name.
+     */
+    removeEngine: function(name){
+        var engines = this.doc.findall('./engine/[@name="' +name+'"]');
+        for(var i=0; i < engines.length; i++){
+            var children = this.doc.getroot().getchildren();
+            var idx = children.indexOf(engines[i]);
+            if(idx > -1){
+                children.splice(idx,1);
+            }
+        }
+    },
+    getEngines: function(){
+        var engines = this.doc.findall('./engine');
+        return engines.map(function(engine){
+            var spec = engine.attrib.spec || engine.attrib.version;
+            return {
+                'name': engine.attrib.name,
+                'spec': spec ? spec : null
+            };
+        });
+    },
+    write:function() {
+        fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
+    }
+};
+
+function featureToPlugin(featureElement) {
+    var plugin = {};
+    plugin.variables = [];
+    var pluginVersion,
+        pluginSrc;
+
+    var nodes = featureElement.findall('param');
+    nodes.forEach(function (element) {
+        var n = element.attrib.name;
+        var v = element.attrib.value;
+        if (n === 'id') {
+            plugin.name = v;
+        } else if (n === 'version') {
+            pluginVersion = v;
+        } else if (n === 'url' || n === 'installPath') {
+            pluginSrc = v;
+        } else {
+            plugin.variables[n] = v;
+        }
+    });
+
+    var spec = pluginSrc || pluginVersion;
+    if (spec) {
+        plugin.spec = spec;
+    }
+
+    return plugin;
+}
+module.exports = ConfigParser;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/configparser/README.md
----------------------------------------------------------------------
diff --git a/cordova-common/src/configparser/README.md b/cordova-common/src/configparser/README.md
new file mode 100644
index 0000000..e5cd1bf
--- /dev/null
+++ b/cordova-common/src/configparser/README.md
@@ -0,0 +1,86 @@
+<!--
+#
+# 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.
+#
+-->
+
+# Cordova-Lib
+
+## ConfigParser
+
+wraps a valid cordova config.xml file 
+
+### Usage
+
+### Include the ConfigParser module in a projet
+
+    var ConfigParser = require('cordova-lib').configparser;
+
+### Create a new ConfigParser
+
+    var config = new ConfigParser('path/to/config/xml/');
+    
+### Utility Functions
+
+#### packageName(id)
+returns document root 'id' attribute value
+#### Usage
+
+    config.packageName: function(id) 
+
+/*
+ * sets document root element 'id' attribute to @id
+ *
+ * @id - new id value
+ *
+ */
+#### setPackageName(id)
+set document root 'id' attribute to 
+ function(id) {
+        this.doc.getroot().attrib['id'] = id;
+    },
+
+### 
+    name: function() {
+        return getNodeTextSafe(this.doc.find('name'));
+    },
+    setName: function(name) {
+        var el = findOrCreate(this.doc, 'name');
+        el.text = name;
+    },
+
+### read the description element
+    
+    config.description()
+
+    var text = "New and improved description of App"
+    setDescription(text)
+    
+### version management
+    version()
+    android_versionCode()
+    ios_CFBundleVersion()
+    setVersion()
+    
+### read author element
+
+   config.author();
+
+### read preference
+
+    config.getPreference(name);

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/events.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/events.js b/cordova-common/src/events.js
new file mode 100644
index 0000000..a6ec340
--- /dev/null
+++ b/cordova-common/src/events.js
@@ -0,0 +1,19 @@
+/**
+    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.
+*/
+module.exports = new (require('events').EventEmitter)();

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/superspawn.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/superspawn.js b/cordova-common/src/superspawn.js
new file mode 100644
index 0000000..b4129ec
--- /dev/null
+++ b/cordova-common/src/superspawn.js
@@ -0,0 +1,154 @@
+/**
+    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 child_process = require('child_process');
+var fs = require('fs');
+var path = require('path');
+var _ = require('underscore');
+var Q = require('q');
+var shell = require('shelljs');
+var events = require('./events');
+var iswin32 = process.platform == 'win32';
+
+// On Windows, spawn() for batch files requires absolute path & having the extension.
+function resolveWindowsExe(cmd) {
+    var winExtensions = ['.exe', '.cmd', '.bat', '.js', '.vbs'];
+    function isValidExe(c) {
+        return winExtensions.indexOf(path.extname(c)) !== -1 && fs.existsSync(c);
+    }
+    if (isValidExe(cmd)) {
+        return cmd;
+    }
+    cmd = shell.which(cmd) || cmd;
+    if (!isValidExe(cmd)) {
+        winExtensions.some(function(ext) {
+            if (fs.existsSync(cmd + ext)) {
+                cmd = cmd + ext;
+                return true;
+            }
+        });
+    }
+    return cmd;
+}
+
+function maybeQuote(a) {
+    if (/^[^"].*[ &].*[^"]/.test(a)) return '"' + a + '"';
+    return a;
+}
+
+// opts:
+//   printCommand: Whether to log the command (default: false)
+//   stdio: 'default' is to capture output and returning it as a string to success (same as exec)
+//          'ignore' means don't bother capturing it
+//          'inherit' means pipe the input & output. This is required for anything that prompts.
+//   env: Map of extra environment variables.
+//   cwd: Working directory for the command.
+//   chmod: If truthy, will attempt to set the execute bit before executing on non-Windows platforms.
+// Returns a promise that succeeds only for return code = 0.
+exports.spawn = function(cmd, args, opts) {
+    args = args || [];
+    opts = opts || {};
+    var spawnOpts = {};
+    var d = Q.defer();
+
+    if (iswin32) {
+        cmd = resolveWindowsExe(cmd);
+        // If we couldn't find the file, likely we'll end up failing,
+        // but for things like "del", cmd will do the trick.
+        if (path.extname(cmd) != '.exe') {
+            var cmdArgs = '"' + [cmd].concat(args).map(maybeQuote).join(' ') + '"';
+            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
+            args = [['/s', '/c', cmdArgs].join(' ')];
+            cmd = 'cmd';
+            spawnOpts.windowsVerbatimArguments = true;
+        } else if (!fs.existsSync(cmd)) {
+            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
+            args = ['/s', '/c', cmd].concat(args).map(maybeQuote);
+        }
+    }
+
+    if (opts.stdio == 'ignore') {
+        spawnOpts.stdio = 'ignore';
+    } else if (opts.stdio == 'inherit') {
+        spawnOpts.stdio = 'inherit';
+    }
+    if (opts.cwd) {
+        spawnOpts.cwd = opts.cwd;
+    }
+    if (opts.env) {
+        spawnOpts.env = _.extend(_.extend({}, process.env), opts.env);
+    }
+    if (opts.chmod && !iswin32) {
+        try {
+            // This fails when module is installed in a system directory (e.g. via sudo npm install)
+            fs.chmodSync(cmd, '755');
+        } catch (e) {
+            // If the perms weren't set right, then this will come as an error upon execution.
+        }
+    }
+
+    events.emit(opts.printCommand ? 'log' : 'verbose', 'Running command: ' + maybeQuote(cmd) + ' ' + args.map(maybeQuote).join(' '));
+
+    var child = child_process.spawn(cmd, args, spawnOpts);
+    var capturedOut = '';
+    var capturedErr = '';
+
+    if (child.stdout) {
+        child.stdout.setEncoding('utf8');
+        child.stdout.on('data', function(data) {
+            capturedOut += data;
+        });
+
+        child.stderr.setEncoding('utf8');
+        child.stderr.on('data', function(data) {
+            capturedErr += data;
+        });
+    }
+
+    child.on('close', whenDone);
+    child.on('error', whenDone);
+    function whenDone(arg) {
+        child.removeListener('close', whenDone);
+        child.removeListener('error', whenDone);
+        var code = typeof arg == 'number' ? arg : arg && arg.code;
+
+        events.emit('verbose', 'Command finished with error code ' + code + ': ' + cmd + ' ' + args);
+        if (code === 0) {
+            d.resolve(capturedOut.trim());
+        } else {
+            var errMsg = cmd + ': Command failed with exit code ' + code;
+            if (capturedErr) {
+                errMsg += ' Error output:\n' + capturedErr.trim();
+            }
+            var err = new Error(errMsg);
+            err.code = code;
+            d.reject(err);
+        }
+    }
+
+    return d.promise;
+};
+
+exports.maybeSpawn = function(cmd, args, opts) {
+    if (fs.existsSync(cmd)) {
+        return exports.spawn(cmd, args, opts);
+    }
+    return Q(null);
+};
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/util/plist-helpers.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/util/plist-helpers.js b/cordova-common/src/util/plist-helpers.js
new file mode 100644
index 0000000..9dee5c6
--- /dev/null
+++ b/cordova-common/src/util/plist-helpers.js
@@ -0,0 +1,101 @@
+/*
+ *
+ * Copyright 2013 Brett Rudd
+ *
+ * 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.
+ *
+*/
+
+// contains PLIST utility functions
+var __     = require('underscore');
+var plist = require('plist');
+
+// adds node to doc at selector
+module.exports.graftPLIST = graftPLIST;
+function graftPLIST(doc, xml, selector) {
+    var obj = plist.parse('<plist>'+xml+'</plist>');
+
+    var node = doc[selector];
+    if (node && Array.isArray(node) && Array.isArray(obj)){
+        node = node.concat(obj);
+        for (var i =0;i<node.length; i++){
+            for (var j=i+1; j<node.length; ++j) {
+              if (nodeEqual(node[i], node[j]))
+                    node.splice(j--,1);
+            }
+        }
+        doc[selector] = node;
+    } else {
+        //plist uses objects for <dict>. If we have two dicts we merge them instead of
+        // overriding the old one. See CB-6472
+        if (node && __.isObject(node) && __.isObject(obj) && !__.isDate(node) && !__.isDate(obj)){//arrays checked above
+            __.extend(obj,node);
+        }
+        doc[selector] = obj;
+    }
+
+    return true;
+}
+
+// removes node from doc at selector
+module.exports.prunePLIST = prunePLIST;
+function prunePLIST(doc, xml, selector) {
+    var obj = plist.parse('<plist>'+xml+'</plist>');
+
+    pruneOBJECT(doc, selector, obj);
+
+    return true;
+}
+
+function pruneOBJECT(doc, selector, fragment) {
+    if (Array.isArray(fragment) && Array.isArray(doc[selector])) {
+        var empty = true;
+        for (var i in fragment) {
+            for (var j in doc[selector]) {
+                empty = pruneOBJECT(doc[selector], j, fragment[i]) && empty;
+            }
+        }
+        if (empty)
+        {
+            delete doc[selector];
+            return true;
+        }
+    }
+    else if (nodeEqual(doc[selector], fragment)) {
+        delete doc[selector];
+        return true;
+    }
+
+    return false;
+}
+
+function nodeEqual(node1, node2) {
+    if (typeof node1 != typeof node2)
+        return false;
+    else if (typeof node1 == 'string') {
+        node2 = escapeRE(node2).replace(new RegExp('\\$[a-zA-Z0-9-_]+','gm'),'(.*?)');
+        return new RegExp('^' + node2 + '$').test(node1);
+    }
+    else {
+        for (var key in node2) {
+            if (!nodeEqual(node1[key], node2[key])) return false;
+        }
+        return true;
+    }
+}
+
+// escape string for use in regex
+function escapeRE(str) {
+    return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '$&');
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/util/xml-helpers.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/util/xml-helpers.js b/cordova-common/src/util/xml-helpers.js
new file mode 100644
index 0000000..8b02989
--- /dev/null
+++ b/cordova-common/src/util/xml-helpers.js
@@ -0,0 +1,266 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * 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.
+ *
+*/
+
+/* jshint sub:true, laxcomma:true */
+
+/**
+ * contains XML utility functions, some of which are specific to elementtree
+ */
+
+var fs = require('fs')
+  , path = require('path')
+  , _ = require('underscore')
+  , et = require('elementtree')
+  ;
+
+module.exports = {
+    // compare two et.XML nodes, see if they match
+    // compares tagName, text, attributes and children (recursively)
+    equalNodes: function(one, two) {
+        if (one.tag != two.tag) {
+            return false;
+        } else if (one.text.trim() != two.text.trim()) {
+            return false;
+        } else if (one._children.length != two._children.length) {
+            return false;
+        }
+
+        var oneAttribKeys = Object.keys(one.attrib),
+            twoAttribKeys = Object.keys(two.attrib),
+            i = 0, attribName;
+
+        if (oneAttribKeys.length != twoAttribKeys.length) {
+            return false;
+        }
+
+        for (i; i < oneAttribKeys.length; i++) {
+            attribName = oneAttribKeys[i];
+
+            if (one.attrib[attribName] != two.attrib[attribName]) {
+                return false;
+            }
+        }
+
+        for (i; i < one._children.length; i++) {
+            if (!module.exports.equalNodes(one._children[i], two._children[i])) {
+                return false;
+            }
+        }
+
+        return true;
+    },
+
+    // adds node to doc at selector, creating parent if it doesn't exist
+    graftXML: function(doc, nodes, selector, after) {
+        var parent = resolveParent(doc, selector);
+        if (!parent) {
+            //Try to create the parent recursively if necessary
+            try {
+                var parentToCreate = et.XML('<' + path.basename(selector) + '>'),
+                    parentSelector = path.dirname(selector);
+
+                this.graftXML(doc, [parentToCreate], parentSelector);
+            } catch (e) {
+                return false;
+            }
+            parent = resolveParent(doc, selector);
+            if (!parent) return false;
+        }
+
+        nodes.forEach(function (node) {
+            // check if child is unique first
+            if (uniqueChild(node, parent)) {
+                var children = parent.getchildren();
+                var insertIdx = after ? findInsertIdx(children, after) : children.length;
+
+                //TODO: replace with parent.insert after the bug in ElementTree is fixed
+                parent.getchildren().splice(insertIdx, 0, node);
+            }
+        });
+
+        return true;
+    },
+
+    // removes node from doc at selector
+    pruneXML: function(doc, nodes, selector) {
+        var parent = resolveParent(doc, selector);
+        if (!parent) return false;
+
+        nodes.forEach(function (node) {
+            var matchingKid = null;
+            if ((matchingKid = findChild(node, parent)) !== null) {
+                // stupid elementtree takes an index argument it doesn't use
+                // and does not conform to the python lib
+                parent.remove(matchingKid);
+            }
+        });
+
+        return true;
+    },
+
+    parseElementtreeSync: function (filename) {
+        var contents = fs.readFileSync(filename, 'utf-8');
+        if(contents) {
+            //Windows is the BOM. Skip the Byte Order Mark.
+            contents = contents.substring(contents.indexOf('<'));
+        }
+        return new et.ElementTree(et.XML(contents));
+    }
+};
+
+function findChild(node, parent) {
+    var matchingKids = parent.findall(node.tag)
+      , i, j;
+
+    for (i = 0, j = matchingKids.length ; i < j ; i++) {
+        if (module.exports.equalNodes(node, matchingKids[i])) {
+            return matchingKids[i];
+        }
+    }
+    return null;
+}
+
+function uniqueChild(node, parent) {
+    var matchingKids = parent.findall(node.tag)
+      , i = 0;
+
+    if (matchingKids.length === 0) {
+        return true;
+    } else  {
+        for (i; i < matchingKids.length; i++) {
+            if (module.exports.equalNodes(node, matchingKids[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+var ROOT = /^\/([^\/]*)/,
+    ABSOLUTE = /^\/([^\/]*)\/(.*)/;
+
+function resolveParent(doc, selector) {
+    var parent, tagName, subSelector;
+
+    // handle absolute selector (which elementtree doesn't like)
+    if (ROOT.test(selector)) {
+        tagName = selector.match(ROOT)[1];
+        // test for wildcard "any-tag" root selector
+        if (tagName == '*' || tagName === doc._root.tag) {
+            parent = doc._root;
+
+            // could be an absolute path, but not selecting the root
+            if (ABSOLUTE.test(selector)) {
+                subSelector = selector.match(ABSOLUTE)[2];
+                parent = parent.find(subSelector);
+            }
+        } else {
+            return false;
+        }
+    } else {
+        parent = doc.find(selector);
+    }
+    return parent;
+}
+
+// Find the index at which to insert an entry. After is a ;-separated priority list
+// of tags after which the insertion should be made. E.g. If we need to
+// insert an element C, and the rule is that the order of children has to be
+// As, Bs, Cs. After will be equal to "C;B;A".
+function findInsertIdx(children, after) {
+    var childrenTags = children.map(function(child) { return child.tag; });
+    var afters = after.split(';');
+    var afterIndexes = afters.map(function(current) { return childrenTags.lastIndexOf(current); });
+    var foundIndex = _.find(afterIndexes, function(index) { return index != -1; });
+
+    //add to the beginning if no matching nodes are found
+    return typeof foundIndex === 'undefined' ? 0 : foundIndex+1;
+}
+
+var BLACKLIST = ['platform', 'feature','plugin','engine'];
+var SINGLETONS = ['content', 'author'];
+function mergeXml(src, dest, platform, clobber) {
+    // Do nothing for blacklisted tags.
+    if (BLACKLIST.indexOf(src.tag) != -1) return;
+
+    //Handle attributes
+    Object.getOwnPropertyNames(src.attrib).forEach(function (attribute) {
+        if (clobber || !dest.attrib[attribute]) {
+            dest.attrib[attribute] = src.attrib[attribute];
+        }
+    });
+    //Handle text
+    if (src.text && (clobber || !dest.text)) {
+        dest.text = src.text;
+    }
+    //Handle platform
+    if (platform) {
+        src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
+            platformElement.getchildren().forEach(mergeChild);
+        });
+    }
+
+    //Handle children
+    src.getchildren().forEach(mergeChild);
+
+    function mergeChild (srcChild) {
+        var srcTag = srcChild.tag,
+            destChild = new et.Element(srcTag),
+            foundChild,
+            query = srcTag + '',
+            shouldMerge = true;
+
+        if (BLACKLIST.indexOf(srcTag) === -1) {
+            if (SINGLETONS.indexOf(srcTag) !== -1) {
+                foundChild = dest.find(query);
+                if (foundChild) {
+                    destChild = foundChild;
+                    dest.remove(destChild);
+                }
+            } else {
+                //Check for an exact match and if you find one don't add
+                Object.getOwnPropertyNames(srcChild.attrib).forEach(function (attribute) {
+                    query += '[@' + attribute + '="' + srcChild.attrib[attribute] + '"]';
+                });
+                var foundChildren = dest.findall(query);
+                for(var i = 0; i < foundChildren.length; i++) {
+                    foundChild = foundChildren[i];
+                    if (foundChild && textMatch(srcChild, foundChild) && (Object.keys(srcChild.attrib).length==Object.keys(foundChild.attrib).length)) {
+                        destChild = foundChild;
+                        dest.remove(destChild);
+                        shouldMerge = false;
+                        break;
+                    }
+                }
+            }
+
+            mergeXml(srcChild, destChild, platform, clobber && shouldMerge);
+            dest.append(destChild);
+        }
+    }
+}
+
+// Expose for testing.
+module.exports.mergeXml = mergeXml;
+
+function textMatch(elm1, elm2) {
+    var text1 = elm1.text ? elm1.text.replace(/\s+/, '') : '',
+        text2 = elm2.text ? elm2.text.replace(/\s+/, '') : '';
+    return (text1 === '' || text1 === text2);
+}


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


[09/10] cordova-lib git commit: Picking CordovaError changes from apache@a3b1fca

Posted by sg...@apache.org.
Picking CordovaError changes from apache@a3b1fca


Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/4909fac1
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/4909fac1
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/4909fac1

Branch: refs/heads/master
Commit: 4909fac13452617bf285f76e5ed151eb6292a1f9
Parents: 59042ba
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Fri Sep 18 14:13:34 2015 +0300
Committer: sgrebnov <v-...@microsoft.com>
Committed: Sun Sep 20 15:14:54 2015 +0300

----------------------------------------------------------------------
 cordova-common/cordova-common.js                |  3 +-
 cordova-common/src/CordovaError.js              | 32 -------
 cordova-common/src/CordovaError/CordovaError.js | 91 ++++++++++++++++++++
 .../CordovaExternalToolErrorContext.js          | 48 +++++++++++
 cordova-common/src/PluginInfo/PluginInfo.js     |  2 +-
 cordova-common/src/configparser/ConfigParser.js |  2 +-
 6 files changed, 143 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/cordova-common.js
----------------------------------------------------------------------
diff --git a/cordova-common/cordova-common.js b/cordova-common/cordova-common.js
index 5873aa7..59b52fc 100644
--- a/cordova-common/cordova-common.js
+++ b/cordova-common/cordova-common.js
@@ -25,7 +25,8 @@ exports = module.exports = {
     superspawn: require('./src/superspawn'),
 
     ActionStack: require('./src/ActionStack'),
-    CordovaError: require('./src/CordovaError'),
+    CordovaError: require('./src/CordovaError/CordovaError'),
+    CordovaExternalToolErrorContext: require('./src/CordovaError/CordovaExternalToolErrorContext'),
     PlatformJson: require('./src/PlatformJson'),
     ConfigParser: require('./src/ConfigParser/ConfigParser.js'),
 

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/src/CordovaError.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/CordovaError.js b/cordova-common/src/CordovaError.js
deleted file mode 100644
index d9989c4..0000000
--- a/cordova-common/src/CordovaError.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-    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.
-*/
-
-/* jshint proto:true */
-
-// A derived exception class. See usage example in cli.js
-// Based on:
-// stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/8460753#8460753
-function CordovaError(message) {
-    Error.captureStackTrace(this, this.constructor);
-    this.name = this.constructor.name;
-    this.message = message;
-}
-CordovaError.prototype.__proto__ = Error.prototype;
-
-module.exports = CordovaError;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/src/CordovaError/CordovaError.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/CordovaError/CordovaError.js b/cordova-common/src/CordovaError/CordovaError.js
new file mode 100644
index 0000000..7262448
--- /dev/null
+++ b/cordova-common/src/CordovaError/CordovaError.js
@@ -0,0 +1,91 @@
+/**
+    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.
+*/
+
+/* jshint proto:true */
+
+var EOL = require('os').EOL;
+
+/**
+ * A derived exception class. See usage example in cli.js
+ * Based on:
+ * stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/8460753#8460753
+ * @param {String} message Error message
+ * @param {Number} [code=0] Error code
+ * @param {CordovaExternalToolErrorContext} [context] External tool error context object
+ * @constructor
+ */
+function CordovaError(message, code, context) {
+    Error.captureStackTrace(this, this.constructor);
+    this.name = this.constructor.name;
+    this.message = message;
+    this.code = code || CordovaError.UNKNOWN_ERROR;
+    this.context = context;
+}
+CordovaError.prototype.__proto__ = Error.prototype;
+
+// TODO: Extend error codes according the projects specifics
+CordovaError.UNKNOWN_ERROR = 0;
+CordovaError.EXTERNAL_TOOL_ERROR = 1;
+
+/**
+ * Translates instance's error code number into error code name, e.g. 0 -> UNKNOWN_ERROR
+ * @returns {string} Error code string name
+ */
+CordovaError.prototype.getErrorCodeName = function() {
+    for(var key in CordovaError) {
+        if(CordovaError.hasOwnProperty(key)) {
+            if(CordovaError[key] === this.code) {
+                return key;
+            }
+        }
+    }
+};
+
+/**
+ * Converts CordovaError instance to string representation
+ * @param   {Boolean}  [isVerbose]  Set up verbose mode. Used to provide more
+ *   details including information about error code name and context
+ * @return  {String}              Stringified error representation
+ */
+CordovaError.prototype.toString = function(isVerbose) {
+    var message = '', codePrefix = '';
+
+    if(this.code !== CordovaError.UNKNOWN_ERROR) {
+        codePrefix = 'code: ' + this.code + (isVerbose ? (' (' + this.getErrorCodeName() + ')') : '') + ' ';
+    }
+
+    if(this.code === CordovaError.EXTERNAL_TOOL_ERROR) {
+        if(typeof this.context !== 'undefined') {
+            if(isVerbose) {
+                message = codePrefix + EOL + this.context.toString(isVerbose) + '\n failed with an error: ' +
+                    this.message + EOL + 'Stack trace: ' + this.stack;
+            } else {
+                message = codePrefix + '\'' + this.context.toString(isVerbose) + '\' ' + this.message;
+            }
+        } else {
+            message = 'External tool failed with an error: ' + this.message;
+        }
+    } else {
+        message = isVerbose ? codePrefix + this.stack : codePrefix + this.message;
+    }
+
+    return message;
+};
+
+module.exports = CordovaError;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js b/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
new file mode 100644
index 0000000..ca9a4aa
--- /dev/null
+++ b/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
@@ -0,0 +1,48 @@
+/**
+ 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.
+ */
+
+/* jshint proto:true */
+
+var path = require('path');
+
+/**
+ * @param {String} cmd Command full path
+ * @param {String[]} args Command args
+ * @param {String} [cwd] Command working directory
+ * @constructor
+ */
+function CordovaExternalToolErrorContext(cmd, args, cwd) {
+    this.cmd = cmd;
+    // Helper field for readability
+    this.cmdShortName = path.basename(cmd);
+    this.args = args;
+    this.cwd = cwd;
+}
+
+CordovaExternalToolErrorContext.prototype.toString = function(isVerbose) {
+    if(isVerbose) {
+        return 'External tool \'' + this.cmdShortName + '\'' +
+            '\nCommand full path: ' + this.cmd + '\nCommand args: ' + this.args +
+            (typeof this.cwd !== 'undefined' ? '\nCommand cwd: ' + this.cwd : '');
+    }
+
+    return this.cmdShortName;
+};
+
+module.exports = CordovaExternalToolErrorContext;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/src/PluginInfo/PluginInfo.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/PluginInfo/PluginInfo.js b/cordova-common/src/PluginInfo/PluginInfo.js
index 10cfdf0..073f3f9 100644
--- a/cordova-common/src/PluginInfo/PluginInfo.js
+++ b/cordova-common/src/PluginInfo/PluginInfo.js
@@ -31,7 +31,7 @@ TODO (kamrik): refactor this to not use sync functions and return promises.
 var path = require('path')
   , fs = require('fs')
   , xml_helpers = require('../util/xml-helpers')
-  , CordovaError = require('../CordovaError')
+  , CordovaError = require('../CordovaError/CordovaError')
   ;
 
 function PluginInfo(dirname) {

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/4909fac1/cordova-common/src/configparser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/configparser/ConfigParser.js b/cordova-common/src/configparser/ConfigParser.js
index 9dcccb5..5006a4d 100644
--- a/cordova-common/src/configparser/ConfigParser.js
+++ b/cordova-common/src/configparser/ConfigParser.js
@@ -21,7 +21,7 @@
 
 var et = require('elementtree'),
     xml= require('../util/xml-helpers'),
-    CordovaError = require('../CordovaError'),
+    CordovaError = require('../CordovaError/CordovaError'),
     fs = require('fs'),
     events = require('../events');
 


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


[06/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5d0d461
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -0,0 +1,636 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1F2BECC013F9785B00A93BF6 /* CDVBattery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F2BECC113F9785B00A93BF6 /* CDVBattery.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */; };
+		1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F3C04CC12BC247D004F9E10 /* CDVContact.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F3C04CD12BC247D004F9E10 /* CDVContact.m */; };
+		1F584B9B1385A28A00ED25E8 /* CDVCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F584B991385A28900ED25E8 /* CDVCapture.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F584B9C1385A28A00ED25E8 /* CDVCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F584B9A1385A28900ED25E8 /* CDVCapture.m */; };
+		1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F92F49E1314023E0046367C /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F92F49F1314023E0046367C /* CDVPluginResult.m */; };
+		301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 301F2F2914F3C9CA003FE9FC /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 302965BB13A94E9D007046C5 /* CDVDebug.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
+		30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */; };
+		307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 307A8F9C1385A2EC00E43782 /* CDVConnection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 307A8F9D1385A2EC00E43782 /* CDVConnection.m */; };
+		30A90B9114588697006178D3 /* JSONKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A90B8F14588697006178D3 /* JSONKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30A90B9314588697006178D3 /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 30A90B9014588697006178D3 /* JSONKit.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+		30B39EBE13D0268B0009682A /* CDVSplashScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B39EBC13D0268B0009682A /* CDVSplashScreen.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30B39EBF13D0268B0009682A /* CDVSplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B39EBD13D0268B0009682A /* CDVSplashScreen.m */; };
+		30C5F1DF15AF9E950052A00D /* CDVDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C5F1DD15AF9E950052A00D /* CDVDevice.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C5F1E015AF9E950052A00D /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C5F1DE15AF9E950052A00D /* CDVDevice.m */; };
+		30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */; };
+		30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C684921407044A004C1A8E /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C684931407044A004C1A8E /* CDVURLProtocol.m */; };
+		30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E33AF013A7E24B00594D64 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E33AF113A7E24B00594D64 /* CDVPlugin.m */; };
+		30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */; };
+		30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3E76876D156A90EE00EB6FA3 /* CDVLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E76876B156A90EE00EB6FA3 /* CDVLogger.m */; };
+		3E76876F156A90EE00EB6FA3 /* CDVLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E76876C156A90EE00EB6FA3 /* CDVLogger.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* CDVViewController.m */; };
+		8852C43F14B65FD800F0E735 /* CDVCordovaView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43814B65FD800F0E735 /* CDVCordovaView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C44114B65FD800F0E735 /* CDVCordovaView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43914B65FD800F0E735 /* CDVCordovaView.m */; };
+		8887FD661090FBE7009987E8 /* CDVCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD261090FBE7009987E8 /* CDVCamera.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD271090FBE7009987E8 /* CDVCamera.m */; };
+		8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */; };
+		8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD2A1090FBE7009987E8 /* CDVContacts.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD2B1090FBE7009987E8 /* CDVContacts.m */; };
+		8887FD6C1090FBE7009987E8 /* CDVDebugConsole.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD6D1090FBE7009987E8 /* CDVDebugConsole.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */; };
+		8887FD701090FBE7009987E8 /* CDVFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD301090FBE7009987E8 /* CDVFile.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD711090FBE7009987E8 /* CDVFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD311090FBE7009987E8 /* CDVFile.m */; };
+		8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */; };
+		8887FD851090FBE7009987E8 /* CDVLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD461090FBE7009987E8 /* CDVLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD861090FBE7009987E8 /* CDVLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD471090FBE7009987E8 /* CDVLocation.m */; };
+		8887FD8D1090FBE7009987E8 /* CDVNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD4E1090FBE7009987E8 /* CDVNotification.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD8E1090FBE7009987E8 /* CDVNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD4F1090FBE7009987E8 /* CDVNotification.m */; };
+		8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD501090FBE7009987E8 /* NSData+Base64.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD511090FBE7009987E8 /* NSData+Base64.m */; };
+		8887FD9D1090FBE7009987E8 /* CDVReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5E1090FBE7009987E8 /* CDVReachability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD9E1090FBE7009987E8 /* CDVReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5F1090FBE7009987E8 /* CDVReachability.m */; };
+		8887FD9F1090FBE7009987E8 /* CDVSound.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD601090FBE7009987E8 /* CDVSound.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD611090FBE7009987E8 /* CDVSound.m */; };
+		88BA573D109BB46F00FB5E78 /* CDVAccelerometer.h in Headers */ = {isa = PBXBuildFile; fileRef = 88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		88BA573E109BB46F00FB5E78 /* CDVAccelerometer.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */; };
+		9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */; };
+		9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */; };
+		C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef = C937A4541337599E002C4C79 /* CDVFileTransfer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */ = {isa = PBXBuildFile; fileRef = C937A4551337599E002C4C79 /* CDVFileTransfer.m */; };
+		EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */; };
+		EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */; };
+		EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; };
+		EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */; };
+		EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */ = {isa = PBXBuildFile; fileRef = EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */; };
+		EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */ = {isa = PBXBuildFile; fileRef = EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */; };
+		EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */ = {isa = PBXBuildFile; fileRef = EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */ = {isa = PBXBuildFile; fileRef = EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVBattery.h; path = Classes/CDVBattery.h; sourceTree = "<group>"; };
+		1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVBattery.m; path = Classes/CDVBattery.m; sourceTree = "<group>"; };
+		1F3C04CC12BC247D004F9E10 /* CDVContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContact.h; path = Classes/CDVContact.h; sourceTree = "<group>"; };
+		1F3C04CD12BC247D004F9E10 /* CDVContact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContact.m; path = Classes/CDVContact.m; sourceTree = "<group>"; };
+		1F584B991385A28900ED25E8 /* CDVCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCapture.h; path = Classes/CDVCapture.h; sourceTree = "<group>"; };
+		1F584B9A1385A28900ED25E8 /* CDVCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCapture.m; path = Classes/CDVCapture.m; sourceTree = "<group>"; };
+		1F92F49E1314023E0046367C /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPluginResult.h; path = Classes/CDVPluginResult.h; sourceTree = "<group>"; };
+		1F92F49F1314023E0046367C /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPluginResult.m; path = Classes/CDVPluginResult.m; sourceTree = "<group>"; };
+		301F2F2914F3C9CA003FE9FC /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDV.h; path = Classes/CDV.h; sourceTree = "<group>"; };
+		302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree = "<group>"; };
+		30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
+		3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h; sourceTree = "<group>"; };
+		3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m; sourceTree = "<group>"; };
+		30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailability.h; path = Classes/CDVAvailability.h; sourceTree = "<group>"; };
+		3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIDevice+Extensions.h"; path = "Classes/UIDevice+Extensions.h"; sourceTree = "<group>"; };
+		3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIDevice+Extensions.m"; path = "Classes/UIDevice+Extensions.m"; sourceTree = "<group>"; };
+		307A8F9C1385A2EC00E43782 /* CDVConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVConnection.h; path = Classes/CDVConnection.h; sourceTree = "<group>"; };
+		307A8F9D1385A2EC00E43782 /* CDVConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVConnection.m; path = Classes/CDVConnection.m; sourceTree = "<group>"; };
+		30A90B8F14588697006178D3 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
+		30A90B9014588697006178D3 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
+		30B39EBC13D0268B0009682A /* CDVSplashScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVSplashScreen.h; path = Classes/CDVSplashScreen.h; sourceTree = "<group>"; };
+		30B39EBD13D0268B0009682A /* CDVSplashScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVSplashScreen.m; path = Classes/CDVSplashScreen.m; sourceTree = "<group>"; };
+		30C5F1DD15AF9E950052A00D /* CDVDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDevice.h; path = Classes/CDVDevice.h; sourceTree = "<group>"; };
+		30C5F1DE15AF9E950052A00D /* CDVDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVDevice.m; path = Classes/CDVDevice.m; sourceTree = "<group>"; };
+		30C6847E1406CB38004C1A8E /* CDVWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWhitelist.h; path = Classes/CDVWhitelist.h; sourceTree = "<group>"; };
+		30C6847F1406CB38004C1A8E /* CDVWhitelist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWhitelist.m; path = Classes/CDVWhitelist.m; sourceTree = "<group>"; };
+		30C684921407044A004C1A8E /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVURLProtocol.h; path = Classes/CDVURLProtocol.h; sourceTree = "<group>"; };
+		30C684931407044A004C1A8E /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVURLProtocol.m; path = Classes/CDVURLProtocol.m; sourceTree = "<group>"; };
+		30E33AF013A7E24B00594D64 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPlugin.h; path = Classes/CDVPlugin.h; sourceTree = "<group>"; };
+		30E33AF113A7E24B00594D64 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPlugin.m; path = Classes/CDVPlugin.m; sourceTree = "<group>"; };
+		30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+QueueAdditions.h"; path = "Classes/NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
+		30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableArray+QueueAdditions.m"; path = "Classes/NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
+		30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegate.h; path = Classes/CDVCommandDelegate.h; sourceTree = "<group>"; };
+		3E76876B156A90EE00EB6FA3 /* CDVLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLogger.m; path = Classes/CDVLogger.m; sourceTree = "<group>"; };
+		3E76876C156A90EE00EB6FA3 /* CDVLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLogger.h; path = Classes/CDVLogger.h; sourceTree = "<group>"; };
+		686357AA141002F100DF4CF2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		686357AC141002F100DF4CF2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		686357AE141002F100DF4CF2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		686357CF14100ADB00DF4CF2 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		686357D014100ADE00DF4CF2 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		686357D214100AE700DF4CF2 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		686357D414100AF200DF4CF2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		686357DC14100B1600DF4CF2 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		68A32D7114102E1C006B237C /* libCordova.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCordova.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		8852C43614B65FD800F0E735 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVViewController.h; path = Classes/CDVViewController.h; sourceTree = "<group>"; };
+		8852C43714B65FD800F0E735 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVViewController.m; path = Classes/CDVViewController.m; sourceTree = "<group>"; };
+		8852C43814B65FD800F0E735 /* CDVCordovaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCordovaView.h; path = Classes/CDVCordovaView.h; sourceTree = "<group>"; };
+		8852C43914B65FD800F0E735 /* CDVCordovaView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCordovaView.m; path = Classes/CDVCordovaView.m; sourceTree = "<group>"; };
+		8887FD261090FBE7009987E8 /* CDVCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCamera.h; path = Classes/CDVCamera.h; sourceTree = "<group>"; };
+		8887FD271090FBE7009987E8 /* CDVCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCamera.m; path = Classes/CDVCamera.m; sourceTree = "<group>"; };
+		8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Extensions.h"; path = "Classes/NSDictionary+Extensions.h"; sourceTree = "<group>"; };
+		8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Extensions.m"; path = "Classes/NSDictionary+Extensions.m"; sourceTree = "<group>"; };
+		8887FD2A1090FBE7009987E8 /* CDVContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContacts.h; path = Classes/CDVContacts.h; sourceTree = "<group>"; };
+		8887FD2B1090FBE7009987E8 /* CDVContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContacts.m; path = Classes/CDVContacts.m; sourceTree = "<group>"; };
+		8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebugConsole.h; path = Classes/CDVDebugConsole.h; sourceTree = "<group>"; };
+		8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVDebugConsole.m; path = Classes/CDVDebugConsole.m; sourceTree = "<group>"; };
+		8887FD301090FBE7009987E8 /* CDVFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVFile.h; path = Classes/CDVFile.h; sourceTree = "<group>"; };
+		8887FD311090FBE7009987E8 /* CDVFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVFile.m; path = Classes/CDVFile.m; sourceTree = "<group>"; };
+		8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVInvokedUrlCommand.h; path = Classes/CDVInvokedUrlCommand.h; sourceTree = "<group>"; };
+		8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVInvokedUrlCommand.m; path = Classes/CDVInvokedUrlCommand.m; sourceTree = "<group>"; };
+		8887FD461090FBE7009987E8 /* CDVLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocation.h; path = Classes/CDVLocation.h; sourceTree = "<group>"; };
+		8887FD471090FBE7009987E8 /* CDVLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocation.m; path = Classes/CDVLocation.m; sourceTree = "<group>"; };
+		8887FD4E1090FBE7009987E8 /* CDVNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVNotification.h; path = Classes/CDVNotification.h; sourceTree = "<group>"; };
+		8887FD4F1090FBE7009987E8 /* CDVNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVNotification.m; path = Classes/CDVNotification.m; sourceTree = "<group>"; };
+		8887FD501090FBE7009987E8 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+Base64.h"; path = "Classes/NSData+Base64.h"; sourceTree = "<group>"; };
+		8887FD511090FBE7009987E8 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+Base64.m"; path = "Classes/NSData+Base64.m"; sourceTree = "<group>"; };
+		8887FD5E1090FBE7009987E8 /* CDVReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVReachability.h; path = Classes/CDVReachability.h; sourceTree = "<group>"; };
+		8887FD5F1090FBE7009987E8 /* CDVReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVReachability.m; path = Classes/CDVReachability.m; sourceTree = "<group>"; };
+		8887FD601090FBE7009987E8 /* CDVSound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVSound.h; path = Classes/CDVSound.h; sourceTree = "<group>"; };
+		8887FD611090FBE7009987E8 /* CDVSound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVSound.m; path = Classes/CDVSound.m; sourceTree = "<group>"; };
+		88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAccelerometer.h; path = Classes/CDVAccelerometer.h; sourceTree = "<group>"; };
+		88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVAccelerometer.m; path = Classes/CDVAccelerometer.m; sourceTree = "<group>"; };
+		9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVGlobalization.h; path = Classes/CDVGlobalization.h; sourceTree = "<group>"; };
+		9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVGlobalization.m; path = Classes/CDVGlobalization.m; sourceTree = "<group>"; };
+		AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CordovaLib_Prefix.pch; sourceTree = SOURCE_ROOT; };
+		C937A4541337599E002C4C79 /* CDVFileTransfer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVFileTransfer.h; path = Classes/CDVFileTransfer.h; sourceTree = "<group>"; };
+		C937A4551337599E002C4C79 /* CDVFileTransfer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVFileTransfer.m; path = Classes/CDVFileTransfer.m; sourceTree = "<group>"; };
+		EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandQueue.h; path = Classes/CDVCommandQueue.h; sourceTree = "<group>"; };
+		EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandQueue.m; path = Classes/CDVCommandQueue.m; sourceTree = "<group>"; };
+		EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegateImpl.h; path = Classes/CDVCommandDelegateImpl.h; sourceTree = "<group>"; };
+		EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandDelegateImpl.m; path = Classes/CDVCommandDelegateImpl.m; sourceTree = "<group>"; };
+		EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVEcho.h; path = Classes/CDVEcho.h; sourceTree = "<group>"; };
+		EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVEcho.m; path = Classes/CDVEcho.m; sourceTree = "<group>"; };
+		EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+Comparisons.h"; path = "Classes/NSArray+Comparisons.h"; sourceTree = "<group>"; };
+		EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Comparisons.m"; path = "Classes/NSArray+Comparisons.m"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D2AAC07C0554694100DB518D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DFFF38A50411DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				68A32D7114102E1C006B237C /* libCordova.a */,
+			);
+			name = Products;
+			sourceTree = CORDOVALIB;
+		};
+		0867D691FE84028FC02AAC07 /* CordovaLib */ = {
+			isa = PBXGroup;
+			children = (
+				8887FD101090FB43009987E8 /* Classes */,
+				32C88DFF0371C24200C91783 /* Other Sources */,
+				0867D69AFE84028FC02AAC07 /* Frameworks */,
+				034768DFFF38A50411DB9C8B /* Products */,
+				30325A0B136B343700982B63 /* VERSION */,
+			);
+			name = CordovaLib;
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				68A32D7414103017006B237C /* AddressBook.framework */,
+				686357DC14100B1600DF4CF2 /* CoreMedia.framework */,
+				686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */,
+				686357CF14100ADB00DF4CF2 /* AVFoundation.framework */,
+				686357D014100ADE00DF4CF2 /* CoreLocation.framework */,
+				686357D214100AE700DF4CF2 /* MobileCoreServices.framework */,
+				686357D414100AF200DF4CF2 /* SystemConfiguration.framework */,
+				686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */,
+				686357AA141002F100DF4CF2 /* UIKit.framework */,
+				686357AC141002F100DF4CF2 /* Foundation.framework */,
+				686357AE141002F100DF4CF2 /* CoreGraphics.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		3054098714B77FF3009841CA /* Cleaver */ = {
+			isa = PBXGroup;
+			children = (
+				8852C43614B65FD800F0E735 /* CDVViewController.h */,
+				8852C43714B65FD800F0E735 /* CDVViewController.m */,
+				8852C43814B65FD800F0E735 /* CDVCordovaView.h */,
+				8852C43914B65FD800F0E735 /* CDVCordovaView.m */,
+				EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */,
+				EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */,
+			);
+			name = Cleaver;
+			sourceTree = "<group>";
+		};
+		32C88DFF0371C24200C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		888700D710922F56009987E8 /* Commands */ = {
+			isa = PBXGroup;
+			children = (
+				30C5F1DD15AF9E950052A00D /* CDVDevice.h */,
+				30C5F1DE15AF9E950052A00D /* CDVDevice.m */,
+				301F2F2914F3C9CA003FE9FC /* CDV.h */,
+				3034979A1513D56A0090E688 /* CDVLocalStorage.h */,
+				3034979B1513D56A0090E688 /* CDVLocalStorage.m */,
+				30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */,
+				30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */,
+				EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */,
+				EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */,
+				30C684921407044A004C1A8E /* CDVURLProtocol.h */,
+				30C684931407044A004C1A8E /* CDVURLProtocol.m */,
+				30C6847E1406CB38004C1A8E /* CDVWhitelist.h */,
+				30C6847F1406CB38004C1A8E /* CDVWhitelist.m */,
+				1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */,
+				1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */,
+				30B39EBC13D0268B0009682A /* CDVSplashScreen.h */,
+				30B39EBD13D0268B0009682A /* CDVSplashScreen.m */,
+				30E33AF013A7E24B00594D64 /* CDVPlugin.h */,
+				30E33AF113A7E24B00594D64 /* CDVPlugin.m */,
+				307A8F9C1385A2EC00E43782 /* CDVConnection.h */,
+				307A8F9D1385A2EC00E43782 /* CDVConnection.m */,
+				1F92F49E1314023E0046367C /* CDVPluginResult.h */,
+				1F92F49F1314023E0046367C /* CDVPluginResult.m */,
+				88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */,
+				88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */,
+				8887FD261090FBE7009987E8 /* CDVCamera.h */,
+				8887FD271090FBE7009987E8 /* CDVCamera.m */,
+				1F584B991385A28900ED25E8 /* CDVCapture.h */,
+				1F584B9A1385A28900ED25E8 /* CDVCapture.m */,
+				1F3C04CC12BC247D004F9E10 /* CDVContact.h */,
+				1F3C04CD12BC247D004F9E10 /* CDVContact.m */,
+				8887FD2A1090FBE7009987E8 /* CDVContacts.h */,
+				8887FD2B1090FBE7009987E8 /* CDVContacts.m */,
+				8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */,
+				8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */,
+				EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */,
+				EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */,
+				8887FD301090FBE7009987E8 /* CDVFile.h */,
+				8887FD311090FBE7009987E8 /* CDVFile.m */,
+				8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */,
+				8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */,
+				C937A4541337599E002C4C79 /* CDVFileTransfer.h */,
+				C937A4551337599E002C4C79 /* CDVFileTransfer.m */,
+				8887FD461090FBE7009987E8 /* CDVLocation.h */,
+				8887FD471090FBE7009987E8 /* CDVLocation.m */,
+				8887FD4E1090FBE7009987E8 /* CDVNotification.h */,
+				8887FD4F1090FBE7009987E8 /* CDVNotification.m */,
+				8887FD5E1090FBE7009987E8 /* CDVReachability.h */,
+				8887FD5F1090FBE7009987E8 /* CDVReachability.m */,
+				8887FD601090FBE7009987E8 /* CDVSound.h */,
+				8887FD611090FBE7009987E8 /* CDVSound.m */,
+				3E76876B156A90EE00EB6FA3 /* CDVLogger.m */,
+				3E76876C156A90EE00EB6FA3 /* CDVLogger.h */,
+				9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */,
+				9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */,
+			);
+			name = Commands;
+			sourceTree = "<group>";
+		};
+		888700D910923009009987E8 /* Util */ = {
+			isa = PBXGroup;
+			children = (
+				3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */,
+				3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */,
+				EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */,
+				EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */,
+				8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */,
+				8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */,
+				302965BB13A94E9D007046C5 /* CDVDebug.h */,
+				30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */,
+				30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */,
+				8887FD501090FBE7009987E8 /* NSData+Base64.h */,
+				8887FD511090FBE7009987E8 /* NSData+Base64.m */,
+			);
+			name = Util;
+			sourceTree = "<group>";
+		};
+		8887FD101090FB43009987E8 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				3054098714B77FF3009841CA /* Cleaver */,
+				888700D710922F56009987E8 /* Commands */,
+				8887FD361090FBE7009987E8 /* JSON */,
+				888700D910923009009987E8 /* Util */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		8887FD361090FBE7009987E8 /* JSON */ = {
+			isa = PBXGroup;
+			children = (
+				30A90B8F14588697006178D3 /* JSONKit.h */,
+				30A90B9014588697006178D3 /* JSONKit.m */,
+			);
+			name = JSON;
+			path = Classes/JSON;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		D2AAC07A0554694100DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8887FD661090FBE7009987E8 /* CDVCamera.h in Headers */,
+				8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */,
+				8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */,
+				8887FD6C1090FBE7009987E8 /* CDVDebugConsole.h in Headers */,
+				8887FD701090FBE7009987E8 /* CDVFile.h in Headers */,
+				8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */,
+				8887FD851090FBE7009987E8 /* CDVLocation.h in Headers */,
+				8887FD8D1090FBE7009987E8 /* CDVNotification.h in Headers */,
+				8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */,
+				8887FD9D1090FBE7009987E8 /* CDVReachability.h in Headers */,
+				8887FD9F1090FBE7009987E8 /* CDVSound.h in Headers */,
+				88BA573D109BB46F00FB5E78 /* CDVAccelerometer.h in Headers */,
+				1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */,
+				1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */,
+				C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */,
+				307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */,
+				1F584B9B1385A28A00ED25E8 /* CDVCapture.h in Headers */,
+				30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */,
+				302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */,
+				30B39EBE13D0268B0009682A /* CDVSplashScreen.h in Headers */,
+				30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */,
+				1F2BECC013F9785B00A93BF6 /* CDVBattery.h in Headers */,
+				30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */,
+				30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */,
+				30A90B9114588697006178D3 /* JSONKit.h in Headers */,
+				8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */,
+				8852C43F14B65FD800F0E735 /* CDVCordovaView.h in Headers */,
+				30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */,
+				301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */,
+				30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */,
+				3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
+				3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */,
+				3E76876F156A90EE00EB6FA3 /* CDVLogger.h in Headers */,
+				EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */,
+				30C5F1DF15AF9E950052A00D /* CDVDevice.h in Headers */,
+				EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */,
+				EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
+				EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
+				9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		D2AAC07D0554694100DB518D /* CordovaLib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */;
+			buildPhases = (
+				D2AAC07A0554694100DB518D /* Headers */,
+				D2AAC07B0554694100DB518D /* Sources */,
+				D2AAC07C0554694100DB518D /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = CordovaLib;
+			productName = CordovaLib;
+			productReference = 68A32D7114102E1C006B237C /* libCordova.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0430;
+			};
+			buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+				en,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07 /* CordovaLib */;
+			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D2AAC07D0554694100DB518D /* CordovaLib */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D2AAC07B0554694100DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */,
+				8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */,
+				8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */,
+				8887FD6D1090FBE7009987E8 /* CDVDebugConsole.m in Sources */,
+				8887FD711090FBE7009987E8 /* CDVFile.m in Sources */,
+				8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */,
+				8887FD861090FBE7009987E8 /* CDVLocation.m in Sources */,
+				8887FD8E1090FBE7009987E8 /* CDVNotification.m in Sources */,
+				8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
+				8887FD9E1090FBE7009987E8 /* CDVReachability.m in Sources */,
+				8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */,
+				88BA573E109BB46F00FB5E78 /* CDVAccelerometer.m in Sources */,
+				1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */,
+				1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */,
+				C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */,
+				307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */,
+				1F584B9C1385A28A00ED25E8 /* CDVCapture.m in Sources */,
+				30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */,
+				30B39EBF13D0268B0009682A /* CDVSplashScreen.m in Sources */,
+				30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */,
+				1F2BECC113F9785B00A93BF6 /* CDVBattery.m in Sources */,
+				30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */,
+				30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */,
+				30A90B9314588697006178D3 /* JSONKit.m in Sources */,
+				8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */,
+				8852C44114B65FD800F0E735 /* CDVCordovaView.m in Sources */,
+				3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
+				3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */,
+				3E76876D156A90EE00EB6FA3 /* CDVLogger.m in Sources */,
+				EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */,
+				30C5F1E015AF9E950052A00D /* CDVDevice.m in Sources */,
+				EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */,
+				EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
+				EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
+				9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB921F08733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				COPY_PHASE_STRIP = NO;
+				DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				INSTALL_PATH = /usr/local/lib;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				PRODUCT_NAME = Cordova;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		1DEB922008733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				INSTALL_PATH = /usr/local/lib;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				PRODUCT_NAME = Cordova;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		1DEB922308733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				ONLY_ACTIVE_ARCH = NO;
+				OTHER_CFLAGS = "-DDEBUG";
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "i386 armv6 armv7 armv7s";
+			};
+			name = Debug;
+		};
+		1DEB922408733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				ONLY_ACTIVE_ARCH = NO;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALID_ARCHS = "i386 armv6 armv7 armv7s";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB921F08733DC00010E9CD /* Debug */,
+				1DEB922008733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB922308733DC00010E9CD /* Debug */,
+				1DEB922408733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/VERSION
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/VERSION b/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/VERSION
new file mode 100644
index 0000000..1545d96
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/CordovaLib/VERSION
@@ -0,0 +1 @@
+3.5.0

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
new file mode 100644
index 0000000..a4d87f9
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
@@ -0,0 +1,498 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A463F14DB0A1B007FEAC7 /* Foundation.framework */; };
+		571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464114DB0A1B007FEAC7 /* UIKit.framework */; };
+		571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */; };
+		571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464514DB0A1B007FEAC7 /* AddressBook.framework */; };
+		571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */; };
+		571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */; };
+		571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */; };
+		571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */; };
+		571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */; };
+		571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465114DB0A1B007FEAC7 /* QuartzCore.framework */; };
+		571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */; };
+		571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */; };
+		571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465714DB0A1B007FEAC7 /* CoreMedia.framework */; };
+		571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */; };
+		571A466014DB0A1B007FEAC7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A465F14DB0A1B007FEAC7 /* main.m */; };
+		571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A466214DB0A1B007FEAC7 /* PhoneGap.framework */; };
+		571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466614DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466A14DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466F14DB0A1B007FEAC7 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A466E14DB0A1B007FEAC7 /* icon.png */; };
+		571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467014DB0A1B007FEAC7 /* icon@2x.png */; };
+		571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467214DB0A1B007FEAC7 /* icon-72.png */; };
+		571A467614DB0A1B007FEAC7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467514DB0A1B007FEAC7 /* Default.png */; };
+		571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467714DB0A1B007FEAC7 /* Default@2x.png */; };
+		571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 571A467914DB0A1B007FEAC7 /* Capture.bundle */; };
+		571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */ = {isa = PBXBuildFile; fileRef = 571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */; };
+		571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A467F14DB0A1B007FEAC7 /* AppDelegate.m */; };
+		571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A468214DB0A1B007FEAC7 /* MainViewController.m */; };
+		571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 571A468414DB0A1B007FEAC7 /* MainViewController.xib */; };
+		577FC36614DB0B620082BA7B /* www in Resources */ = {isa = PBXBuildFile; fileRef = 577FC36514DB0B620082BA7B /* www */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		571A463B14DB0A1B007FEAC7 /* ChildApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChildApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		571A463F14DB0A1B007FEAC7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		571A464114DB0A1B007FEAC7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		571A464514DB0A1B007FEAC7 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+		571A465114DB0A1B007FEAC7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		571A465714DB0A1B007FEAC7 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		571A465B14DB0A1B007FEAC7 /* ChildApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ChildApp-Info.plist"; sourceTree = "<group>"; };
+		571A465D14DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		571A465F14DB0A1B007FEAC7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		571A466114DB0A1B007FEAC7 /* ChildApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ChildApp-Prefix.pch"; sourceTree = "<group>"; };
+		571A466214DB0A1B007FEAC7 /* PhoneGap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhoneGap.framework; path = /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework; sourceTree = "<absolute>"; };
+		571A466714DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Resources/en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466B14DB0A1B007FEAC7 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Resources/es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466E14DB0A1B007FEAC7 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon.png; path = Resources/icons/icon.png; sourceTree = "<group>"; };
+		571A467014DB0A1B007FEAC7 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon@2x.png"; path = "Resources/icons/icon@2x.png"; sourceTree = "<group>"; };
+		571A467214DB0A1B007FEAC7 /* icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-72.png"; path = "Resources/icons/icon-72.png"; sourceTree = "<group>"; };
+		571A467514DB0A1B007FEAC7 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/splash/Default.png; sourceTree = "<group>"; };
+		571A467714DB0A1B007FEAC7 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/splash/Default@2x.png"; sourceTree = "<group>"; };
+		571A467914DB0A1B007FEAC7 /* Capture.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Capture.bundle; path = Resources/Capture.bundle; sourceTree = "<group>"; };
+		571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PhoneGap.plist; sourceTree = "<group>"; };
+		571A467E14DB0A1B007FEAC7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = "<group>"; };
+		571A467F14DB0A1B007FEAC7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = "<group>"; };
+		571A468114DB0A1B007FEAC7 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = "<group>"; };
+		571A468214DB0A1B007FEAC7 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = "<group>"; };
+		571A468414DB0A1B007FEAC7 /* MainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainViewController.xib; path = Classes/MainViewController.xib; sourceTree = "<group>"; };
+		571A468714DB0A1B007FEAC7 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = Plugins/README; sourceTree = "<group>"; };
+		577FC36514DB0B620082BA7B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		571A463514DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */,
+				571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */,
+				571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */,
+				571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */,
+				571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */,
+				571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */,
+				571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */,
+				571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */,
+				571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */,
+				571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */,
+				571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */,
+				571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */,
+				571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */,
+				571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463814DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		571A462D14DB0A1A007FEAC7 = {
+			isa = PBXGroup;
+			children = (
+				577FC36514DB0B620082BA7B /* www */,
+				571A465914DB0A1B007FEAC7 /* ChildApp */,
+				571A463E14DB0A1B007FEAC7 /* Frameworks */,
+				571A463C14DB0A1B007FEAC7 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		571A463C14DB0A1B007FEAC7 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				571A463B14DB0A1B007FEAC7 /* ChildApp.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		571A463E14DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				571A463F14DB0A1B007FEAC7 /* Foundation.framework */,
+				571A464114DB0A1B007FEAC7 /* UIKit.framework */,
+				571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */,
+				571A464514DB0A1B007FEAC7 /* AddressBook.framework */,
+				571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */,
+				571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */,
+				571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */,
+				571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */,
+				571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */,
+				571A465114DB0A1B007FEAC7 /* QuartzCore.framework */,
+				571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */,
+				571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */,
+				571A465714DB0A1B007FEAC7 /* CoreMedia.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		571A465914DB0A1B007FEAC7 /* ChildApp */ = {
+			isa = PBXGroup;
+			children = (
+				571A466214DB0A1B007FEAC7 /* PhoneGap.framework */,
+				571A466414DB0A1B007FEAC7 /* Resources */,
+				571A467D14DB0A1B007FEAC7 /* Classes */,
+				571A468614DB0A1B007FEAC7 /* Plugins */,
+				571A465A14DB0A1B007FEAC7 /* Supporting Files */,
+			);
+			path = ChildApp;
+			sourceTree = "<group>";
+		};
+		571A465A14DB0A1B007FEAC7 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				571A465B14DB0A1B007FEAC7 /* ChildApp-Info.plist */,
+				571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */,
+				571A465F14DB0A1B007FEAC7 /* main.m */,
+				571A466114DB0A1B007FEAC7 /* ChildApp-Prefix.pch */,
+				571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */,
+				571A468414DB0A1B007FEAC7 /* MainViewController.xib */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		571A466414DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				571A467914DB0A1B007FEAC7 /* Capture.bundle */,
+				571A466514DB0A1B007FEAC7 /* en.lproj */,
+				571A466914DB0A1B007FEAC7 /* es.lproj */,
+				571A466D14DB0A1B007FEAC7 /* icons */,
+				571A467414DB0A1B007FEAC7 /* splash */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		571A466514DB0A1B007FEAC7 /* en.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466614DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = en.lproj;
+			sourceTree = "<group>";
+		};
+		571A466914DB0A1B007FEAC7 /* es.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466A14DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = es.lproj;
+			sourceTree = "<group>";
+		};
+		571A466D14DB0A1B007FEAC7 /* icons */ = {
+			isa = PBXGroup;
+			children = (
+				571A466E14DB0A1B007FEAC7 /* icon.png */,
+				571A467014DB0A1B007FEAC7 /* icon@2x.png */,
+				571A467214DB0A1B007FEAC7 /* icon-72.png */,
+			);
+			name = icons;
+			sourceTree = "<group>";
+		};
+		571A467414DB0A1B007FEAC7 /* splash */ = {
+			isa = PBXGroup;
+			children = (
+				571A467514DB0A1B007FEAC7 /* Default.png */,
+				571A467714DB0A1B007FEAC7 /* Default@2x.png */,
+			);
+			name = splash;
+			sourceTree = "<group>";
+		};
+		571A467D14DB0A1B007FEAC7 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				571A467E14DB0A1B007FEAC7 /* AppDelegate.h */,
+				571A467F14DB0A1B007FEAC7 /* AppDelegate.m */,
+				571A468114DB0A1B007FEAC7 /* MainViewController.h */,
+				571A468214DB0A1B007FEAC7 /* MainViewController.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		571A468614DB0A1B007FEAC7 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				571A468714DB0A1B007FEAC7 /* README */,
+			);
+			name = Plugins;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		571A463A14DB0A1B007FEAC7 /* ChildApp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "ChildApp" */;
+			buildPhases = (
+				571A463414DB0A1B007FEAC7 /* Sources */,
+				571A463514DB0A1B007FEAC7 /* Frameworks */,
+				571A463614DB0A1B007FEAC7 /* Resources */,
+				571A463714DB0A1B007FEAC7 /* Sources */,
+				571A463814DB0A1B007FEAC7 /* Frameworks */,
+				571A463914DB0A1B007FEAC7 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ChildApp;
+			productName = ChildApp;
+			productReference = 571A463B14DB0A1B007FEAC7 /* ChildApp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		571A462F14DB0A1A007FEAC7 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0420;
+			};
+			buildConfigurationList = 571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "ChildApp" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				es,
+			);
+			mainGroup = 571A462D14DB0A1A007FEAC7;
+			productRefGroup = 571A463C14DB0A1B007FEAC7 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				571A463A14DB0A1B007FEAC7 /* ChildApp */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		571A463614DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */,
+				571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466F14DB0A1B007FEAC7 /* icon.png in Resources */,
+				571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */,
+				571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */,
+				571A467614DB0A1B007FEAC7 /* Default.png in Resources */,
+				571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */,
+				571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */,
+				571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */,
+				571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */,
+				577FC36614DB0B620082BA7B /* www in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		571A463914DB0A1B007FEAC7 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "\n\t\t\t\t\t\t\t\tif [ ! -d \"$PROJECT_DIR/www\" ] ; then\n\t\t\t\t\t\t\t\t\tcp -R /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework/www \"$PROJECT_DIR\"\n\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\t\t# detect www folder reference in project, if missing, print warning\n\t\t\t\t\t\t\t\tgrep \"{isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = \\\"<group>\\\"; };\" \"$PROJECT_DIR/$PROJECT_NAME.xcodeproj/project.pbxproj\"\n\t\t\t\t\t\t\t\trc=$? \n\t\t\t\t\t\t\t\tif [ $rc != 0 ] ; then\n\t\t\t\t\t\t\t\techo -e \"warning: Missing - Add $PROJECT_DIR/www as a folder reference in your project. Just drag and drop the folder into your project, into the Project Navigator of Xcode 4. Make sure you select the second radio-button: 'Create folder references for any added folders' (which will create a blue folder)\" 1>&2\n\t\t\t\t\t\t\t\tfi\t\t\t\t\t\t\t";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		571A463414DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A466014DB0A1B007FEAC7 /* main.m in Sources */,
+				571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */,
+				571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463714DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A465D14DB0A1B007FEAC7 /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		571A466614DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466714DB0A1B007FEAC7 /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		571A466A14DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466B14DB0A1B007FEAC7 /* es */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		571A468814DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		571A468914DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		571A468B14DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = /Users/Shared/PhoneGap/Frameworks;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "ChildApp/ChildApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "ChildApp/ChildApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		571A468C14DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				FRAMEWORK_SEARCH_PATHS = /Users/Shared/PhoneGap/Frameworks;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "ChildApp/ChildApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "ChildApp/ChildApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "ChildApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468814DB0A1B007FEAC7 /* Debug */,
+				571A468914DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "ChildApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468B14DB0A1B007FEAC7 /* Debug */,
+				571A468C14DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 571A462F14DB0A1A007FEAC7 /* Project object */;
+}


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


[08/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
CB-9598 Adds tests and fixtures based on existing cordova-lib ones


Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/59042bae
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/59042bae
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/59042bae

Branch: refs/heads/master
Commit: 59042baebaf8bee0763339dfe61ad538960b0897
Parents: 28ce0d1
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Wed Sep 16 16:39:41 2015 +0300
Committer: sgrebnov <v-...@microsoft.com>
Committed: Sun Sep 20 15:14:54 2015 +0300

----------------------------------------------------------------------
 cordova-common/spec/ActionStack.spec.js         |   77 +
 .../spec/ConfigChanges/ConfigChanges.spec.js    |  445 +
 cordova-common/spec/ConfigParser.spec.js        |  224 -
 .../spec/ConfigParser/ConfigParser.spec.js      |  224 +
 .../spec/PluginInfo/PluginInfo.spec.js          |   50 +
 .../spec/PluginInfo/PluginInfoProvider.spec.js  |   33 +
 .../fixtures/plugins/ChildBrowser/plugin.xml    |  126 +
 .../ChildBrowser/src/android/ChildBrowser.java  |   19 +
 .../plugins/ChildBrowser/www/childbrowser.js    |   19 +
 .../ChildBrowser/www/childbrowser/image.jpg     |    1 +
 .../ChildBrowser/www/childbrowser_file.html     |    1 +
 .../fixtures/plugins/com.adobe.vars/plugin.xml  |   59 +
 .../plugins/org.apache.plist/plugin.xml         |   54 +
 .../plugins/org.test.configtest/plugin.xml      |   61 +
 .../org.test.multiple-children/plugin.xml       |  108 +
 .../org.test.plugins.childbrowser/plugin.xml    |  124 +
 .../src/android/ChildBrowser.java               |    1 +
 .../src/ios/ChildBrowser.bundle/arrow_left.png  |    1 +
 .../ios/ChildBrowser.bundle/arrow_left@2x.png   |    1 +
 .../src/ios/ChildBrowser.bundle/arrow_right.png |    1 +
 .../ios/ChildBrowser.bundle/arrow_right@2x.png  |    1 +
 .../src/ios/ChildBrowser.bundle/but_refresh.png |    1 +
 .../ios/ChildBrowser.bundle/but_refresh@2x.png  |    1 +
 .../src/ios/ChildBrowser.bundle/compass.png     |    1 +
 .../src/ios/ChildBrowser.bundle/compass@2x.png  |    1 +
 .../src/ios/ChildBrowserCommand.h               |    1 +
 .../src/ios/ChildBrowserCommand.m               |    1 +
 .../src/ios/ChildBrowserViewController.h        |    1 +
 .../src/ios/ChildBrowserViewController.m        |    1 +
 .../src/ios/ChildBrowserViewController.xib      |    1 +
 .../src/ios/TargetDirTest.h                     |    1 +
 .../src/ios/TargetDirTest.m                     |    1 +
 .../src/ios/preserveDirs/PreserveDirsTest.h     |    1 +
 .../src/ios/preserveDirs/PreserveDirsTest.m     |    1 +
 .../www/childbrowser.js                         |    1 +
 .../www/childbrowser/image.jpg                  |    1 +
 .../www/childbrowser_file.html                  |    1 +
 .../android-resource.xml                        |    1 +
 .../org.test.plugins.dummyplugin/extra.gradle   |    1 +
 .../plugin-lib/AndroidManifest.xml              |    5 +
 .../plugin-lib/libFile                          |    1 +
 .../plugin-lib/project.properties               |    1 +
 .../org.test.plugins.dummyplugin/plugin.xml     |  207 +
 .../src/android/DummyPlugin.java                |    1 +
 .../src/blackberry10/index.js                   |    1 +
 .../src/ios/Custom.framework/someFheader.h      |    1 +
 .../src/ios/Custom.framework/somebinlib         |    1 +
 .../src/ios/DummyPlugin.bundle                  |    1 +
 .../src/ios/DummyPluginCommand.h                |    1 +
 .../src/ios/DummyPluginCommand.m                |    1 +
 .../src/ios/SourceWithFramework.m               |    1 +
 .../src/ios/TargetDirTest.h                     |    1 +
 .../src/ios/TargetDirTest.m                     |    1 +
 .../src/ios/libsqlite3.dylib                    |    1 +
 .../src/tizen/dummer.js                         |    1 +
 .../src/windows/dummer.js                       |    1 +
 .../src/windows/dummy1.dll                      |    0
 .../src/windows/dummy1.vcxproj                  |    7 +
 .../src/windows/dummy2.dll                      |    0
 .../src/windows/dummy2.vcxproj                  |    7 +
 .../src/windows/dummy3.dll                      |    0
 .../src/windows/dummy3.vcxproj                  |    7 +
 .../src/windows/dummy4.dll                      |    0
 .../src/windows/dummy4.vcxproj                  |    7 +
 .../src/wp7/DummyPlugin.cs                      |    1 +
 .../src/wp8/DummyPlugin.cs                      |    1 +
 .../www/dummyplugin.js                          |    1 +
 .../www/dummyplugin/image.jpg                   |    1 +
 .../plugins/org.test.shareddeps/plugin.xml      |   34 +
 .../projects/android/AndroidManifest.xml        |   69 +
 .../projects/android/assets/www/.gitkeep        |    0
 .../projects/android/res/xml/config.xml         |   54 +
 .../spec/fixtures/projects/android/src/.gitkeep |    0
 .../projects/android_two/AndroidManifest.xml    |   69 +
 .../projects/android_two/assets/www/.gitkeep    |    0
 .../projects/android_two/res/xml/config.xml     |   54 +
 .../fixtures/projects/android_two/src/.gitkeep  |    0
 .../android_two_no_perms/AndroidManifest.xml    |   49 +
 .../android_two_no_perms/assets/www/.gitkeep    |    0
 .../android_two_no_perms/res/xml/config.xml     |   54 +
 .../projects/android_two_no_perms/src/.gitkeep  |    0
 .../CordovaLib.xcodeproj/project.pbxproj        |  636 ++
 .../projects/ios-config-xml/CordovaLib/VERSION  |    1 +
 .../SampleApp.xcodeproj/project.orig.pbxproj    |  498 ++
 .../SampleApp.xcodeproj/project.pbxproj         |  496 ++
 .../SampleApp/SampleApp-Info.plist              |   82 +
 .../ios-config-xml/SampleApp/config.xml         |   59 +
 .../projects/ios-config-xml/www/.gitkeep        |    0
 .../spec/fixtures/projects/windows/bom_test.xml |   24 +
 .../windows8/CordovaApp_TemporaryKey.pfx        |  Bin 0 -> 2504 bytes
 .../fixtures/projects/windows8/TestApp.jsproj   |   81 +
 .../spec/fixtures/projects/windows8/TestApp.sln |   46 +
 .../projects/windows8/package.appxmanifest      |   27 +
 .../projects/windows8/www/cordova-2.6.0.js      | 8075 ++++++++++++++++++
 .../projects/windows8/www/css/index.css         |  115 +
 .../fixtures/projects/windows8/www/img/logo.png |  Bin 0 -> 11600 bytes
 .../projects/windows8/www/img/smalllogo.png     |  Bin 0 -> 2831 bytes
 .../projects/windows8/www/img/splashscreen.png  |  Bin 0 -> 24855 bytes
 .../projects/windows8/www/img/storelogo.png     |  Bin 0 -> 4052 bytes
 .../fixtures/projects/windows8/www/index.html   |   42 +
 .../fixtures/projects/windows8/www/js/index.js  |   49 +
 cordova-common/spec/fixtures/test-config.xml    |   43 +
 cordova-common/spec/util/xml-helpers.spec.js    |  271 +
 103 files changed, 12611 insertions(+), 224 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/ActionStack.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ActionStack.spec.js b/cordova-common/spec/ActionStack.spec.js
new file mode 100644
index 0000000..5fb6819
--- /dev/null
+++ b/cordova-common/spec/ActionStack.spec.js
@@ -0,0 +1,77 @@
+/**
+    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 path = require('path');
+var action_stack = require('../src/ActionStack');
+var android_one_project = path.join(__dirname, '..', 'projects', 'android_one');
+
+describe('action-stack', function() {
+    var stack;
+    beforeEach(function() {
+        stack = new action_stack();
+    });
+    describe('processing of actions', function() {
+        it('should process actions one at a time until all are done', function() {
+            var first_spy = jasmine.createSpy();
+            var first_args = [1];
+            var second_spy = jasmine.createSpy();
+            var second_args = [2];
+            var third_spy = jasmine.createSpy();
+            var third_args = [3];
+            stack.push(stack.createAction(first_spy, first_args, function(){}, []));
+            stack.push(stack.createAction(second_spy, second_args, function(){}, []));
+            stack.push(stack.createAction(third_spy, third_args, function(){}, []));
+            stack.process('android', android_one_project);
+            expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+            expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+            expect(third_spy).toHaveBeenCalledWith(third_args[0]);
+        });
+        it('should revert processed actions if an exception occurs', function() {
+            spyOn(console, 'log');
+            var first_spy = jasmine.createSpy();
+            var first_args = [1];
+            var first_reverter = jasmine.createSpy();
+            var first_reverter_args = [true];
+            var process_err = new Error('process_err');
+            var second_spy = jasmine.createSpy().andCallFake(function() {
+                throw process_err;
+            });
+            var second_args = [2];
+            var third_spy = jasmine.createSpy();
+            var third_args = [3];
+            stack.push(stack.createAction(first_spy, first_args, first_reverter, first_reverter_args));
+            stack.push(stack.createAction(second_spy, second_args, function(){}, []));
+            stack.push(stack.createAction(third_spy, third_args, function(){}, []));
+            // process should throw
+            var error;
+            runs(function() {
+                stack.process('android', android_one_project).fail(function(err) { error = err; });
+            });
+            waitsFor(function(){ return error; }, 'process promise never resolved', 500);
+            runs(function() {
+                expect(error).toEqual(process_err);
+                // first two actions should have been called, but not the third
+                expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+                expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+                expect(third_spy).not.toHaveBeenCalledWith(third_args[0]);
+                // first reverter should have been called after second action exploded
+                expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0]);
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/ConfigChanges/ConfigChanges.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ConfigChanges/ConfigChanges.spec.js b/cordova-common/spec/ConfigChanges/ConfigChanges.spec.js
new file mode 100644
index 0000000..2c854c6
--- /dev/null
+++ b/cordova-common/spec/ConfigChanges/ConfigChanges.spec.js
@@ -0,0 +1,445 @@
+/**
+    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.
+*/
+
+/* jshint sub:true */
+
+var configChanges = require('../../src/ConfigChanges/ConfigChanges'),
+    xml_helpers = require('../../src/util/xml-helpers'),
+    fs      = require('fs'),
+    os      = require('osenv'),
+    et      = require('elementtree'),
+    path    = require('path'),
+    shell   = require('shelljs'),
+    xcode = require('xcode'),
+    temp    = path.join(os.tmpdir(), 'plugman'),
+    dummyplugin = path.join(__dirname, '../fixtures/plugins/org.test.plugins.dummyplugin'),
+    cbplugin = path.join(__dirname, '../fixtures/plugins/org.test.plugins.childbrowser'),
+    childrenplugin = path.join(__dirname, '../fixtures/plugins/org.test.multiple-children'),
+    shareddepsplugin = path.join(__dirname, '../fixtures/plugins/org.test.shareddeps'),
+    configplugin = path.join(__dirname, '../fixtures/plugins/org.test.configtest'),
+    varplugin = path.join(__dirname, '../fixtures/plugins/com.adobe.vars'),
+    plistplugin = path.join(__dirname, '../fixtures/plugins/org.apache.plist'),
+    android_two_project = path.join(__dirname, '../fixtures/projects/android_two/*'),
+    android_two_no_perms_project = path.join(__dirname, '../fixtures/projects/android_two_no_perms', '*'),
+    ios_config_xml = path.join(__dirname, '../fixtures/projects/ios-config-xml/*'),
+    windows_testapp_jsproj = path.join(__dirname, '../fixtures/projects/windows8/TestApp.jsproj'),
+    plugins_dir = path.join(temp, 'cordova', 'plugins');
+var mungeutil = require('../../src/ConfigChanges/munge-util');
+var PlatformJson = require('../../src/PlatformJson');
+var PluginInfoProvider = require('../../src/PluginInfo/PluginInfoProvider');
+var PluginInfo = require('../../src/PluginInfo/PluginInfo');
+
+// TODO: dont do fs so much
+
+var pluginInfoProvider = new PluginInfoProvider();
+
+function innerXML(xmltext) {
+    return xmltext.replace(/^<[\w\s\-=\/"\.]+>/, '').replace(/<\/[\w\s\-=\/"\.]+>$/,'');
+}
+
+function get_munge_change(munge, keys) {
+    return mungeutil.deep_find.apply(null, arguments);
+}
+
+describe('config-changes module', function() {
+    beforeEach(function() {
+        shell.mkdir('-p', temp);
+        shell.mkdir('-p', plugins_dir);
+    });
+    afterEach(function() {
+        shell.rm('-rf', temp);
+    });
+
+    describe('queue methods', function() {
+        describe('addInstalledPluginToPrepareQueue', function() {
+            it('should append specified plugin to platform.json', function() {
+                var platformJson = new PlatformJson(null, 'android', null);
+                platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
+                var json = platformJson.root;
+                expect(json.prepare_queue.installed[0].plugin).toEqual('org.test.plugins.dummyplugin');
+                expect(json.prepare_queue.installed[0].vars).toEqual({});
+            });
+            it('should append specified plugin with any variables to platform.json', function() {
+                var platformJson = new PlatformJson(null, 'android', null);
+                platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {'dude':'man'});
+                var json = platformJson.root;
+                expect(json.prepare_queue.installed[0].plugin).toEqual('org.test.plugins.dummyplugin');
+                expect(json.prepare_queue.installed[0].vars).toEqual({'dude':'man'});
+            });
+        });
+
+        describe('addUninstalledPluginToPrepareQueue', function() {
+            it('should append specified plugin to platform.json', function() {
+                var platformJson = new PlatformJson(null, 'android', null);
+                platformJson.addUninstalledPluginToPrepareQueue('org.test.plugins.dummyplugin');
+                var json = platformJson.root;
+                expect(json.prepare_queue.uninstalled[0].plugin).toEqual('org.test.plugins.dummyplugin');
+            });
+        });
+    });
+
+    describe('load method', function() {
+        it('should return an empty config json object if file doesn\'t exist', function() {
+            var platformJson = PlatformJson.load(plugins_dir, 'android');
+            expect(platformJson.root).toBeDefined();
+            expect(platformJson.root.prepare_queue).toBeDefined();
+            expect(platformJson.root.config_munge).toBeDefined();
+            expect(platformJson.root.installed_plugins).toBeDefined();
+        });
+        it('should return the json file if it exists', function() {
+            var filepath = path.join(plugins_dir, 'android.json');
+            var json = {
+                prepare_queue: {installed: [], uninstalled: []},
+                config_munge: {files: {'some_file': {parents: {'some_parent': [{'xml': 'some_change', 'count': 1}]}}}},
+                installed_plugins: {},
+                dependent_plugins: {}};
+            fs.writeFileSync(filepath, JSON.stringify(json), 'utf-8');
+            var platformJson = PlatformJson.load(plugins_dir, 'android');
+            expect(JSON.stringify(json)).toEqual(JSON.stringify(platformJson.root));
+        });
+    });
+
+    describe('save method', function() {
+        it('should write out specified json', function() {
+            var filepath = path.join(plugins_dir, 'android.json');
+            var platformJson = new PlatformJson(filepath, 'android', {foo:true});
+            platformJson.save();
+            expect(JSON.parse(fs.readFileSync(filepath, 'utf-8'))).toEqual(platformJson.root);
+        });
+    });
+
+    describe('generate_plugin_config_munge method', function() {
+        describe('for android projects', function() {
+            beforeEach(function() {
+                shell.cp('-rf', android_two_project, temp);
+            });
+            it('should return a flat config hierarchy for simple, one-off config changes', function() {
+                var xml;
+                var dummy_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(dummyplugin, 'plugin.xml'), 'utf-8')));
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(dummyplugin), {});
+                expect(munge.files['AndroidManifest.xml']).toBeDefined();
+                expect(munge.files['AndroidManifest.xml'].parents['/manifest/application']).toBeDefined();
+                xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="AndroidManifest.xml"]'))).write({xml_declaration:false});
+                xml = innerXML(xml);
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest/application', xml).count).toEqual(1);
+                expect(munge.files['res/xml/plugins.xml']).toBeDefined();
+                expect(munge.files['res/xml/plugins.xml'].parents['/plugins']).toBeDefined();
+                xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="res/xml/plugins.xml"]'))).write({xml_declaration:false});
+                xml = innerXML(xml);
+                expect(get_munge_change(munge, 'res/xml/plugins.xml', '/plugins', xml).count).toEqual(1);
+                expect(munge.files['res/xml/config.xml']).toBeDefined();
+                expect(munge.files['res/xml/config.xml'].parents['/cordova/plugins']).toBeDefined();
+                xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="res/xml/config.xml"]'))).write({xml_declaration:false});
+                xml = innerXML(xml);
+                expect(get_munge_change(munge, 'res/xml/config.xml', '/cordova/plugins', xml).count).toEqual(1);
+            });
+            it('should split out multiple children of config-file elements into individual leaves', function() {
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {PACKAGE_NAME: 'com.alunny.childapp'});
+                expect(munge.files['AndroidManifest.xml']).toBeDefined();
+                expect(munge.files['AndroidManifest.xml'].parents['/manifest']).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.READ_PHONE_STATE" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.INTERNET" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.GET_ACCOUNTS" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.WAKE_LOCK" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" />')).toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />')).toBeDefined();
+            });
+            it('should not use xml comments as config munge leaves', function() {
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {});
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!--library-->')).not.toBeDefined();
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!-- GCM connects to Google Services. -->')).not.toBeDefined();
+            });
+            it('should increment config hierarchy leaves if different config-file elements target the same file + selector + xml', function() {
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(configplugin), {});
+                expect(get_munge_change(munge, 'res/xml/config.xml', '/widget', '<poop />').count).toEqual(2);
+            });
+            it('should take into account interpolation variables', function() {
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(childrenplugin), {PACKAGE_NAME:'ca.filmaj.plugins'});
+                expect(get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="ca.filmaj.plugins.permission.C2D_MESSAGE" />')).toBeDefined();
+            });
+            it('should create munges for platform-agnostic config.xml changes', function() {
+                var munger = new configChanges.PlatformMunger('android', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(dummyplugin), {});
+                expect(get_munge_change(munge, 'config.xml', '/*', '<access origin="build.phonegap.com" />')).toBeDefined();
+                expect(get_munge_change(munge, 'config.xml', '/*', '<access origin="s3.amazonaws.com" />')).toBeDefined();
+            });
+        });
+
+        describe('for ios projects', function() {
+            beforeEach(function() {
+                shell.cp('-rf', ios_config_xml, temp);
+            });
+            it('should special case framework elements for ios', function() {
+                var munger = new configChanges.PlatformMunger('ios', temp, 'unused', null, pluginInfoProvider);
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(cbplugin), {});
+                expect(munge.files['framework']).toBeDefined();
+                expect(get_munge_change(munge, 'framework', 'libsqlite3.dylib', false)).toBeDefined();
+                expect(get_munge_change(munge, 'framework', 'social.framework', true)).toBeDefined();
+                expect(get_munge_change(munge, 'framework', 'music.framework', false)).toBeDefined();
+                expect(munge.files['framework'].parents['Custom.framework']).not.toBeDefined();
+            });
+        });
+        describe('for windows project', function() {
+            beforeEach(function() {
+                shell.cp('-rf', windows_testapp_jsproj, temp);
+            });
+            it('should special case config-file elements for windows', function() {
+                var munger = new configChanges.PlatformMunger('windows', temp, 'unused', null, pluginInfoProvider);
+
+                var munge = munger.generate_plugin_config_munge(pluginInfoProvider.get(configplugin), {});
+                var packageAppxManifest = munge.files['package.appxmanifest'];
+                var windows80AppxManifest = munge.files['package.windows80.appxmanifest'];
+                var windows81AppxManifest = munge.files['package.windows.appxmanifest'];
+                var winphone81AppxManifest = munge.files['package.phone.appxmanifest'];
+                var windows10AppxManifest = munge.files['package.windows10.appxmanifest'];
+
+                expect(packageAppxManifest.parents['/Parent/Capabilities'][0].xml).toBe('<Capability Note="should-exist-for-all-appxmanifest-target-files" />');
+                expect(windows80AppxManifest.parents['/Parent/Capabilities'][0].xml).toBe('<Capability Note="should-exist-for-win8-only" />');
+                expect(windows80AppxManifest.parents['/Parent/Capabilities'][1].xml).toBe('<Capability Note="should-exist-for-win8-and-win81-win-only" />');
+                expect(windows80AppxManifest.parents['/Parent/Capabilities'][2].xml).toBe('<Capability Note="should-exist-for-win8-and-win81-both" />');
+                expect(windows81AppxManifest.parents['/Parent/Capabilities'][0].xml).toBe('<Capability Note="should-exist-for-win81-win-and-phone" />');
+                expect(windows81AppxManifest.parents['/Parent/Capabilities'][1].xml).toBe('<Capability Note="should-exist-for-win8-and-win81-win-only" />');
+                expect(windows81AppxManifest.parents['/Parent/Capabilities'][2].xml).toBe('<Capability Note="should-exist-for-win8-and-win81-both" />');
+                expect(winphone81AppxManifest.parents['/Parent/Capabilities'][0].xml).toBe('<Capability Note="should-exist-for-win81-win-and-phone" />');
+                expect(winphone81AppxManifest.parents['/Parent/Capabilities'][1].xml).toBe('<Capability Note="should-exist-for-win81-phone-only" />');
+                expect(winphone81AppxManifest.parents['/Parent/Capabilities'][2].xml).toBe('<Capability Note="should-exist-for-win8-and-win81-both" />');
+                expect(windows10AppxManifest.parents['/Parent/Capabilities'][0].xml).toBe('<Capability Note="should-exist-in-win10-only" />');
+            });
+        });
+    });
+
+    describe('processing of plugins (via process method)', function() {
+        beforeEach(function() {
+            shell.cp('-rf', dummyplugin, plugins_dir);
+        });
+        it('should generate config munges for queued plugins', function() {
+            shell.cp('-rf', android_two_project, temp);
+            var platformJson = PlatformJson.load(plugins_dir, 'android');
+            platformJson.root.prepare_queue.installed = [{'plugin':'org.test.plugins.dummyplugin', 'vars':{}}];
+            var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+            var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
+            munger.process(plugins_dir);
+            expect(spy).toHaveBeenCalledWith(jasmine.any(PluginInfo), {});
+        });
+        describe(': installation', function() {
+            describe('of xml config files', function() {
+                beforeEach(function() {
+                    shell.cp('-rf', android_two_project, temp);
+                });
+                it('should call graftXML for every new config munge it introduces (every leaf in config munge that does not exist)', function() {
+                    var platformJson = PlatformJson.load(plugins_dir, 'android');
+                    platformJson.root.prepare_queue.installed = [{'plugin':'org.test.plugins.dummyplugin', 'vars':{}}];
+
+                    var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
+
+                    var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                    munger.process(plugins_dir);
+                    expect(spy.calls.length).toEqual(4);
+                    expect(spy.argsForCall[0][2]).toEqual('/*');
+                    expect(spy.argsForCall[1][2]).toEqual('/*');
+                    expect(spy.argsForCall[2][2]).toEqual('/manifest/application');
+                    expect(spy.argsForCall[3][2]).toEqual('/cordova/plugins');
+                });
+                it('should not call graftXML for a config munge that already exists from another plugin', function() {
+                    shell.cp('-rf', configplugin, plugins_dir);
+                    var platformJson = PlatformJson.load(plugins_dir, 'android');
+                    platformJson.addInstalledPluginToPrepareQueue('org.test.configtest', {});
+
+                    var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
+                    var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                    munger.process(plugins_dir);
+                    expect(spy.calls.length).toEqual(1);
+                });
+                it('should not call graftXML for a config munge targeting a config file that does not exist', function() {
+                    var platformJson = PlatformJson.load(plugins_dir, 'android');
+                    platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
+
+                    var spy = spyOn(fs, 'readFileSync').andCallThrough();
+
+                    var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                    munger.process(plugins_dir);
+                    expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
+                });
+            });
+            describe('of plist config files', function() {
+                it('should write empty string nodes with no whitespace', function() {
+                    shell.cp('-rf', ios_config_xml, temp);
+                    shell.cp('-rf', varplugin, plugins_dir);
+                    var platformJson = PlatformJson.load(plugins_dir, 'ios');
+                    platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {});
+                    configChanges.process(plugins_dir, temp, 'ios', platformJson, pluginInfoProvider);
+                    expect(fs.readFileSync(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf-8')).toMatch(/<key>APluginNode<\/key>\n    <string><\/string>/m);
+                });
+                it('should merge dictionaries and arrays, removing duplicates', function() {
+                    shell.cp('-rf', ios_config_xml, temp);
+                    shell.cp('-rf', plistplugin, plugins_dir);
+                    var platformJson = PlatformJson.load(plugins_dir, 'ios');
+                    platformJson.addInstalledPluginToPrepareQueue('org.apache.plist', {});
+                    configChanges.process(plugins_dir, temp, 'ios', platformJson, pluginInfoProvider);
+                    expect(fs.readFileSync(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf-8')).toMatch(/<key>UINewsstandIcon<\/key>[\s\S]*<key>CFBundlePrimaryIcon<\/key>/);
+                    expect(fs.readFileSync(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf-8')).toMatch(/<string>schema-b<\/string>/);
+                    expect(fs.readFileSync(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf-8')).not.toMatch(/(<string>schema-a<\/string>[^]*){2,}/);
+                });
+            });
+            describe('of pbxproject framework files', function() {
+                var xcode_add;
+                beforeEach(function() {
+                    shell.cp('-rf', ios_config_xml, temp);
+                    shell.cp('-rf', cbplugin, plugins_dir);
+                    xcode_add = spyOn(xcode.project.prototype, 'addFramework').andCallThrough();
+                });
+                it('should call into xcode.addFramework if plugin has <framework> file defined and is ios',function() {
+                    var platformJson = PlatformJson.load(plugins_dir, 'ios');
+                    platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.childbrowser', {});
+                    var munger = new configChanges.PlatformMunger('ios', temp, platformJson, pluginInfoProvider);
+                    munger.process(plugins_dir);
+                    expect(xcode_add).toHaveBeenCalledWith('libsqlite3.dylib', {weak:false});
+                    expect(xcode_add).toHaveBeenCalledWith('social.framework', {weak:true});
+                    expect(xcode_add).toHaveBeenCalledWith('music.framework', {weak:false});
+                    expect(xcode_add).not.toHaveBeenCalledWith('Custom.framework');
+                });
+            });
+            it('should resolve wildcard config-file targets to the project, if applicable', function() {
+                shell.cp('-rf', ios_config_xml, temp);
+                shell.cp('-rf', cbplugin, plugins_dir);
+                var platformJson = PlatformJson.load(plugins_dir, 'ios');
+                platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.childbrowser', {});
+                var spy = spyOn(fs, 'readFileSync').andCallThrough();
+
+                var munger = new configChanges.PlatformMunger('ios', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'SampleApp-Info.plist').replace(/\\/g, '/'), 'utf8');
+            });
+            it('should move successfully installed plugins from queue to installed plugins section, and include/retain vars if applicable', function() {
+                shell.cp('-rf', android_two_project, temp);
+                shell.cp('-rf', varplugin, plugins_dir);
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'hi'}, true);
+
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                expect(platformJson.root.prepare_queue.installed.length).toEqual(0);
+                expect(platformJson.root.installed_plugins['com.adobe.vars']).toBeDefined();
+                expect(platformJson.root.installed_plugins['com.adobe.vars']['API_KEY']).toEqual('hi');
+            });
+        });
+
+        describe(': uninstallation', function() {
+            it('should call pruneXML for every config munge it completely removes from the app (every leaf that is decremented to 0)', function() {
+                shell.cp('-rf', android_two_project, temp);
+
+                // Run through an "install"
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                // Now set up an uninstall and make sure prunexml is called properly
+                platformJson.addUninstalledPluginToPrepareQueue('org.test.plugins.dummyplugin');
+                var spy = spyOn(xml_helpers, 'pruneXML').andReturn(true);
+                munger.process(plugins_dir);
+                expect(spy.calls.length).toEqual(4);
+                expect(spy.argsForCall[0][2]).toEqual('/*');
+                expect(spy.argsForCall[1][2]).toEqual('/*');
+                expect(spy.argsForCall[2][2]).toEqual('/manifest/application');
+                expect(spy.argsForCall[3][2]).toEqual('/cordova/plugins');
+            });
+            it('should generate a config munge that interpolates variables into config changes, if applicable', function() {
+                shell.cp('-rf', android_two_project, temp);
+                shell.cp('-rf', varplugin, plugins_dir);
+                // Run through an "install"
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'canucks'});
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                // Now set up an uninstall and make sure prunexml is called properly
+                platformJson.addUninstalledPluginToPrepareQueue('com.adobe.vars');
+                var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
+                munger.process(plugins_dir);
+                var munge_params = spy.mostRecentCall.args;
+                expect(munge_params[0]).toEqual(jasmine.any(PluginInfo));
+                expect(munge_params[0].dir).toEqual(path.join(plugins_dir, 'com.adobe.vars'));
+                expect(munge_params[1]['API_KEY']).toEqual('canucks');
+            });
+            it('should not call pruneXML for a config munge that another plugin depends on', function() {
+                shell.cp('-rf', android_two_no_perms_project, temp);
+                shell.cp('-rf', childrenplugin, plugins_dir);
+                shell.cp('-rf', shareddepsplugin, plugins_dir);
+
+                // Run through and "install" two plugins (they share a permission for INTERNET)
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('org.test.multiple-children', {});
+                platformJson.addInstalledPluginToPrepareQueue('org.test.shareddeps', {});
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                // Now set up an uninstall for multi-child plugin
+                platformJson.addUninstalledPluginToPrepareQueue('org.test.multiple-children');
+                munger.process(plugins_dir);
+                munger.save_all();
+                var am_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8')));
+                var permission = am_xml.find('./uses-permission');
+                expect(permission).toBeDefined();
+                expect(permission.attrib['android:name']).toEqual('android.permission.INTERNET');
+            });
+            it('should not call pruneXML for a config munge targeting a config file that does not exist', function() {
+                shell.cp('-rf', android_two_project, temp);
+                // install a plugin
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('org.test.plugins.dummyplugin', {});
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                // set up an uninstall for the same plugin
+                platformJson.addUninstalledPluginToPrepareQueue('org.test.plugins.dummyplugin');
+
+                var spy = spyOn(fs, 'readFileSync').andCallThrough();
+                munger.process(plugins_dir);
+
+                expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
+            });
+            it('should remove uninstalled plugins from installed plugins list', function() {
+                shell.cp('-rf', android_two_project, temp);
+                shell.cp('-rf', varplugin, plugins_dir);
+                // install the var plugin
+                var platformJson = PlatformJson.load(plugins_dir, 'android');
+                platformJson.addInstalledPluginToPrepareQueue('com.adobe.vars', {'API_KEY':'eat my shorts'});
+                var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                munger.process(plugins_dir);
+
+                // queue up an uninstall for the same plugin
+                platformJson.addUninstalledPluginToPrepareQueue('com.adobe.vars');
+                munger.process(plugins_dir);
+
+                expect(platformJson.root.prepare_queue.uninstalled.length).toEqual(0);
+                expect(platformJson.root.installed_plugins['com.adobe.vars']).not.toBeDefined();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ConfigParser.spec.js b/cordova-common/spec/ConfigParser.spec.js
deleted file mode 100644
index a888cf4..0000000
--- a/cordova-common/spec/ConfigParser.spec.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
-    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 path = require('path'),
-    fs = require('fs'),
-    ConfigParser = require('../src/configparser/ConfigParser'),
-    xml = path.join(__dirname, 'test-config.xml'),
-    xml_contents = fs.readFileSync(xml, 'utf-8');
-
-describe('config.xml parser', function () {
-    var readFile;
-    beforeEach(function() {
-        readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
-    });
-
-    it('should create an instance based on an xml file', function() {
-        var cfg;
-        expect(function () {
-            cfg = new ConfigParser(xml);
-        }).not.toThrow();
-        expect(cfg).toBeDefined();
-        expect(cfg.doc).toBeDefined();
-    });
-
-    describe('methods', function() {
-        var cfg;
-        beforeEach(function() {
-            cfg = new ConfigParser(xml);
-        });
-
-        describe('package name / id', function() {
-            it('should get the (default) packagename', function() {
-                expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
-            });
-            it('should allow setting the packagename', function() {
-                cfg.setPackageName('this.is.bat.country');
-                expect(cfg.packageName()).toEqual('this.is.bat.country');
-            });
-        });
-
-        describe('package name / android-packageName', function() {
-            it('should get the android packagename', function() {
-                expect(cfg.android_packageName()).toEqual('io.cordova.hellocordova.android');
-            });
-        });
-
-        describe('package name / ios-CFBundleIdentifier', function() {
-            it('should get the ios packagename', function() {
-                expect(cfg.ios_CFBundleIdentifier()).toEqual('io.cordova.hellocordova.ios');
-            });
-        });
-
-        describe('version', function() {
-            it('should get the version', function() {
-                expect(cfg.version()).toEqual('0.0.1');
-            });
-            it('should allow setting the version', function() {
-                cfg.setVersion('2.0.1');
-                expect(cfg.version()).toEqual('2.0.1');
-            });
-        });
-
-        describe('app name', function() {
-            it('should get the (default) app name', function() {
-                expect(cfg.name()).toEqual('Hello Cordova');
-            });
-            it('should allow setting the app name', function() {
-                cfg.setName('this.is.bat.country');
-                expect(cfg.name()).toEqual('this.is.bat.country');
-            });
-        });
-        describe('preference', function() {
-            it('should return the value of a global preference', function() {
-                expect(cfg.getPreference('fullscreen')).toEqual('true');
-            });
-            it('should return the value of a platform-specific preference', function() {
-                expect(cfg.getPreference('android-minSdkVersion', 'android')).toEqual('10');
-            });
-            it('should return an empty string for a non-existing preference', function() {
-                expect(cfg.getPreference('zimzooo!')).toEqual('');
-            });
-        });
-        describe('global preference', function() {
-            it('should return the value of a global preference', function() {
-                expect(cfg.getGlobalPreference('orientation')).toEqual('portrait');
-            });
-            it('should return an empty string for a non-existing preference', function() {
-                expect(cfg.getGlobalPreference('foobar')).toEqual('');
-            });
-        });
-        describe('platform-specific preference', function() {
-            it('should return the value of a platform specific preference', function() {
-                expect(cfg.getPlatformPreference('orientation', 'android')).toEqual('landscape');
-            });
-            it('should return an empty string when querying for a non-existing preference', function() {
-                expect(cfg.getPlatformPreference('foobar', 'android')).toEqual('');
-            });
-            it('should return an empty string when querying with unsupported platform', function() {
-                expect(cfg.getPlatformPreference('orientation', 'foobar')).toEqual('');
-            });
-        });
-        describe('plugin',function(){
-            it('should read plugin id list', function() {
-               var expectedList = [
-                   'org.apache.cordova.pluginwithvars',
-                   'org.apache.cordova.pluginwithurl',
-                   'org.apache.cordova.pluginwithversion',
-                   'org.apache.cordova.pluginwithurlandversion',
-                   'org.apache.cordova.justaplugin',
-                   'org.apache.cordova.legacyfeatureversion',
-                   'org.apache.cordova.legacyfeatureurl',
-                   'org.apache.cordova.legacyfeatureversionandurl'
-               ];
-               var list = cfg.getPluginIdList();
-               expect(list.length).toEqual(expectedList.length);
-               expectedList.forEach(function(plugin){
-                   expect(list).toContain(plugin);
-               });
-            });
-            it('should read plugin given id', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.justaplugin');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.justaplugin');
-                expect(plugin.variables).toBeDefined();
-            });
-            it('should not read plugin given undefined id', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.undefinedplugin');
-                expect(plugin).not.toBeDefined();
-            });
-            it('should read plugin with src and store it in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurl');
-            });
-            it('should read plugin with version and store it in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithversion');
-                expect(plugin.spec).toEqual('1.1.1');
-            });
-            it('should read plugin with source and version and store source in spec field', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurlandversion');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurlandversion');
-            });
-            it('should read plugin variables', function () {
-                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithvars');
-                expect(plugin.variables).toBeDefined();
-                expect(plugin.variables.var).toBeDefined();
-                expect(plugin.variables.var).toEqual('varvalue');
-            });
-            it('should allow adding a new plugin', function(){
-                cfg.addPlugin({name:'myplugin'});
-                var plugins = cfg.doc.findall('plugin');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).toContain('myplugin');
-            });
-            it('should allow adding features with params', function(){
-                cfg.addPlugin({name:'aplugin'}, [{name:'paraname',value:'paravalue'}]);
-                // Additional check for new parameters syntax
-                cfg.addPlugin({name:'bplugin'}, {paraname: 'paravalue'});
-                var plugins = cfg.doc.findall('plugin')
-                .filter(function (plugin) {
-                    return plugin.attrib.name === 'aplugin' || plugin.attrib.name === 'bplugin';
-                });
-                expect(plugins.length).toBe(2);
-                plugins.forEach(function (plugin) {
-                    var variables = plugin.findall('variable');
-                    expect(variables[0].attrib.name).toEqual('paraname');
-                    expect(variables[0].attrib.value).toEqual('paravalue');
-                });
-            });
-            it('should be able to read legacy feature entries with a version', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversion');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversion');
-                expect(plugin.spec).toEqual('1.2.3');
-                expect(plugin.variables).toBeDefined();
-                expect(plugin.variables.aVar).toEqual('aValue');
-            });
-            it('should be able to read legacy feature entries with a url', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureurl');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureurl');
-            });
-            it('should be able to read legacy feature entries with a version and a url', function(){
-                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversionandurl');
-                expect(plugin).toBeDefined();
-                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversionandurl');
-                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureversionandurl');
-            });
-            it('it should remove given plugin', function(){
-                cfg.removePlugin('org.apache.cordova.justaplugin');
-                var plugins = cfg.doc.findall('plugin');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).not.toContain('org.apache.cordova.justaplugin');
-            });
-            it('it should remove given legacy feature id', function(){
-                cfg.removePlugin('org.apache.cordova.legacyplugin');
-                var plugins = cfg.doc.findall('feature');
-                var pluginNames = plugins.map(function(plugin){
-                    return plugin.attrib.name;
-                });
-                expect(pluginNames).not.toContain('org.apache.cordova.legacyplugin');
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/ConfigParser/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ConfigParser/ConfigParser.spec.js b/cordova-common/spec/ConfigParser/ConfigParser.spec.js
new file mode 100644
index 0000000..9d4696d
--- /dev/null
+++ b/cordova-common/spec/ConfigParser/ConfigParser.spec.js
@@ -0,0 +1,224 @@
+/**
+    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 path = require('path'),
+    fs = require('fs'),
+    ConfigParser = require('../../src/ConfigParser/ConfigParser'),
+    xml = path.join(__dirname, '../fixtures/test-config.xml'),
+    xml_contents = fs.readFileSync(xml, 'utf-8');
+
+describe('config.xml parser', function () {
+    var readFile;
+    beforeEach(function() {
+        readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
+    });
+
+    it('should create an instance based on an xml file', function() {
+        var cfg;
+        expect(function () {
+            cfg = new ConfigParser(xml);
+        }).not.toThrow();
+        expect(cfg).toBeDefined();
+        expect(cfg.doc).toBeDefined();
+    });
+
+    describe('methods', function() {
+        var cfg;
+        beforeEach(function() {
+            cfg = new ConfigParser(xml);
+        });
+
+        describe('package name / id', function() {
+            it('should get the (default) packagename', function() {
+                expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
+            });
+            it('should allow setting the packagename', function() {
+                cfg.setPackageName('this.is.bat.country');
+                expect(cfg.packageName()).toEqual('this.is.bat.country');
+            });
+        });
+
+        describe('package name / android-packageName', function() {
+            it('should get the android packagename', function() {
+                expect(cfg.android_packageName()).toEqual('io.cordova.hellocordova.android');
+            });
+        });
+
+        describe('package name / ios-CFBundleIdentifier', function() {
+            it('should get the ios packagename', function() {
+                expect(cfg.ios_CFBundleIdentifier()).toEqual('io.cordova.hellocordova.ios');
+            });
+        });
+
+        describe('version', function() {
+            it('should get the version', function() {
+                expect(cfg.version()).toEqual('0.0.1');
+            });
+            it('should allow setting the version', function() {
+                cfg.setVersion('2.0.1');
+                expect(cfg.version()).toEqual('2.0.1');
+            });
+        });
+
+        describe('app name', function() {
+            it('should get the (default) app name', function() {
+                expect(cfg.name()).toEqual('Hello Cordova');
+            });
+            it('should allow setting the app name', function() {
+                cfg.setName('this.is.bat.country');
+                expect(cfg.name()).toEqual('this.is.bat.country');
+            });
+        });
+        describe('preference', function() {
+            it('should return the value of a global preference', function() {
+                expect(cfg.getPreference('fullscreen')).toEqual('true');
+            });
+            it('should return the value of a platform-specific preference', function() {
+                expect(cfg.getPreference('android-minSdkVersion', 'android')).toEqual('10');
+            });
+            it('should return an empty string for a non-existing preference', function() {
+                expect(cfg.getPreference('zimzooo!')).toEqual('');
+            });
+        });
+        describe('global preference', function() {
+            it('should return the value of a global preference', function() {
+                expect(cfg.getGlobalPreference('orientation')).toEqual('portrait');
+            });
+            it('should return an empty string for a non-existing preference', function() {
+                expect(cfg.getGlobalPreference('foobar')).toEqual('');
+            });
+        });
+        describe('platform-specific preference', function() {
+            it('should return the value of a platform specific preference', function() {
+                expect(cfg.getPlatformPreference('orientation', 'android')).toEqual('landscape');
+            });
+            it('should return an empty string when querying for a non-existing preference', function() {
+                expect(cfg.getPlatformPreference('foobar', 'android')).toEqual('');
+            });
+            it('should return an empty string when querying with unsupported platform', function() {
+                expect(cfg.getPlatformPreference('orientation', 'foobar')).toEqual('');
+            });
+        });
+        describe('plugin',function(){
+            it('should read plugin id list', function() {
+               var expectedList = [
+                   'org.apache.cordova.pluginwithvars',
+                   'org.apache.cordova.pluginwithurl',
+                   'org.apache.cordova.pluginwithversion',
+                   'org.apache.cordova.pluginwithurlandversion',
+                   'org.apache.cordova.justaplugin',
+                   'org.apache.cordova.legacyfeatureversion',
+                   'org.apache.cordova.legacyfeatureurl',
+                   'org.apache.cordova.legacyfeatureversionandurl'
+               ];
+               var list = cfg.getPluginIdList();
+               expect(list.length).toEqual(expectedList.length);
+               expectedList.forEach(function(plugin){
+                   expect(list).toContain(plugin);
+               });
+            });
+            it('should read plugin given id', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.justaplugin');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.justaplugin');
+                expect(plugin.variables).toBeDefined();
+            });
+            it('should not read plugin given undefined id', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.undefinedplugin');
+                expect(plugin).not.toBeDefined();
+            });
+            it('should read plugin with src and store it in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurl');
+            });
+            it('should read plugin with version and store it in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithversion');
+                expect(plugin.spec).toEqual('1.1.1');
+            });
+            it('should read plugin with source and version and store source in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurlandversion');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurlandversion');
+            });
+            it('should read plugin variables', function () {
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithvars');
+                expect(plugin.variables).toBeDefined();
+                expect(plugin.variables.var).toBeDefined();
+                expect(plugin.variables.var).toEqual('varvalue');
+            });
+            it('should allow adding a new plugin', function(){
+                cfg.addPlugin({name:'myplugin'});
+                var plugins = cfg.doc.findall('plugin');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).toContain('myplugin');
+            });
+            it('should allow adding features with params', function(){
+                cfg.addPlugin({name:'aplugin'}, [{name:'paraname',value:'paravalue'}]);
+                // Additional check for new parameters syntax
+                cfg.addPlugin({name:'bplugin'}, {paraname: 'paravalue'});
+                var plugins = cfg.doc.findall('plugin')
+                .filter(function (plugin) {
+                    return plugin.attrib.name === 'aplugin' || plugin.attrib.name === 'bplugin';
+                });
+                expect(plugins.length).toBe(2);
+                plugins.forEach(function (plugin) {
+                    var variables = plugin.findall('variable');
+                    expect(variables[0].attrib.name).toEqual('paraname');
+                    expect(variables[0].attrib.value).toEqual('paravalue');
+                });
+            });
+            it('should be able to read legacy feature entries with a version', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversion');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversion');
+                expect(plugin.spec).toEqual('1.2.3');
+                expect(plugin.variables).toBeDefined();
+                expect(plugin.variables.aVar).toEqual('aValue');
+            });
+            it('should be able to read legacy feature entries with a url', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureurl');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureurl');
+            });
+            it('should be able to read legacy feature entries with a version and a url', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversionandurl');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversionandurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureversionandurl');
+            });
+            it('it should remove given plugin', function(){
+                cfg.removePlugin('org.apache.cordova.justaplugin');
+                var plugins = cfg.doc.findall('plugin');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).not.toContain('org.apache.cordova.justaplugin');
+            });
+            it('it should remove given legacy feature id', function(){
+                cfg.removePlugin('org.apache.cordova.legacyplugin');
+                var plugins = cfg.doc.findall('feature');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).not.toContain('org.apache.cordova.legacyplugin');
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/PluginInfo/PluginInfo.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/PluginInfo/PluginInfo.spec.js b/cordova-common/spec/PluginInfo/PluginInfo.spec.js
new file mode 100644
index 0000000..935d8cd
--- /dev/null
+++ b/cordova-common/spec/PluginInfo/PluginInfo.spec.js
@@ -0,0 +1,50 @@
+/**
+    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 PluginInfo = require('../../src/PluginInfo/PluginInfo'),
+    path = require('path');
+
+var pluginsDir = path.join(__dirname, '../fixtures/plugins');
+
+describe('PluginInfo', function () {
+    it('should read a plugin.xml file', function () {
+        var p, prefs, assets, deps, configFiles, infos, srcFiles;
+        var headerFiles, libFiles, resourceFiles;
+        expect(function () {
+            p = new PluginInfo(path.join(pluginsDir, 'ChildBrowser'));
+            prefs = p.getPreferences('android');
+            assets = p.getAssets('android');
+            deps = p.getDependencies('android');
+            configFiles = p.getConfigFiles('android');
+            infos = p.getInfo('android');
+            srcFiles = p.getSourceFiles('android');
+            headerFiles = p.getHeaderFiles('android');
+            libFiles = p.getLibFiles('android');
+            resourceFiles = p.getResourceFiles('android');
+        }).not.toThrow();
+        expect(p).toBeDefined();
+        expect(p.name).toEqual('Child Browser');
+        // TODO: Add some expectations for results of getSomething.
+    });
+    it('should throw when there is no plugin.xml file', function () {
+        expect(function () {
+            new PluginInfo('/non/existent/dir');
+        }).toThrow();
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/PluginInfo/PluginInfoProvider.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/PluginInfo/PluginInfoProvider.spec.js b/cordova-common/spec/PluginInfo/PluginInfoProvider.spec.js
new file mode 100644
index 0000000..40ec6bb
--- /dev/null
+++ b/cordova-common/spec/PluginInfo/PluginInfoProvider.spec.js
@@ -0,0 +1,33 @@
+/**
+    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 PluginInfoProvider = require('../../src/PluginInfo/PluginInfoProvider'),
+    path = require('path');
+
+var pluginsDir = path.join(__dirname, '../fixtures/plugins');
+
+describe('PluginInfoProvider', function () {
+    describe('getAllWithinSearchPath', function () {
+        it('should load all plugins in a dir', function () {
+            var pluginInfoProvider = new PluginInfoProvider();
+            var plugins = pluginInfoProvider.getAllWithinSearchPath(pluginsDir);
+            expect(plugins.length).not.toBe(0);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/ChildBrowser/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/ChildBrowser/plugin.xml b/cordova-common/spec/fixtures/plugins/ChildBrowser/plugin.xml
new file mode 100644
index 0000000..11ddd86
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/ChildBrowser/plugin.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="com.phonegap.plugins.childbrowser"
+    version="0.6.0">
+
+    <name>Child Browser</name>
+
+    <asset src="www/childbrowser" target="childbrowser" />
+    <asset src="www/childbrowser_file.html" target="childbrowser_file.html" />
+
+    <js-module src="www/childbrowser.js" name="ChildBrowser">
+        <clobbers target="childbrowser" />
+    </js-module>
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+        <access origin="s3.amazonaws.com" />
+    </config-file>
+    
+    <info>No matter what platform you are installing to, this notice is very important.</info>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity android:name="com.phonegap.plugins.childBrowser.ChildBrowser"
+                      android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
+
+        <!-- CDV < 2.0 -->
+        <config-file target="res/xml/plugins.xml" parent="/plugins">
+            <plugin name="ChildBrowser"
+                value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+        </config-file>
+
+        <!-- CDV 2.0+ (for now) -->
+        <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+            <plugin name="ChildBrowser"
+                value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+        </config-file>
+
+        <source-file src="src/android/ChildBrowser.java"
+                target-dir="src/com/phonegap/plugins/childBrowser" />
+        <info>Please make sure you read this because it is very important to complete the installation of your plugin.</info>
+    </platform>
+
+    <!-- ios -->
+    <platform name="ios">
+        <plugins-plist key="com.phonegap.plugins.childbrowser"
+            string="ChildBrowserCommand" />
+
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="ChildBrowser"
+                value="ChildBrowserCommand" />
+        </config-file>
+
+        <resource-file src="src/ios/ChildBrowser.bundle" />
+        <resource-file src="src/ios/ChildBrowserViewController.xib" />
+
+        <config-file target="*-Info.plist" parent="AppId">
+            <string>$APP_ID</string>
+        </config-file>
+        
+        <config-file target="*-Info.plist" parent="CFBundleURLTypes">
+            <array>
+              <dict>
+                <key>PackageName</key>
+                <string>$PACKAGE_NAME</string>
+              </dict>
+            </array>
+        </config-file>
+
+        <header-file src="src/ios/ChildBrowserCommand.h" />
+        <header-file src="src/ios/ChildBrowserViewController.h" />
+        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir"/>
+
+        <source-file src="src/ios/ChildBrowserCommand.m" />
+        <source-file src="src/ios/ChildBrowserViewController.m" />
+        <source-file src="src/ios/preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
+        <header-file src="src/ios/TargetDirTest.m" target-dir="targetDir"/>
+
+        <!-- framework for testing (not actual dependency of ChildBrowser -->
+        <framework src="libsqlite3.dylib" />
+        <framework src="social.framework" weak="true" />
+        <framework src="music.framework" weak="rabbit" />
+    </platform>
+
+    <!-- wp8 -->
+    <platform name="wp8">
+        <resource-file src="src\wp7\Images\appbar.back.rest.png" />
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="ChildBrowser"
+                value="ChildBrowser"/>
+        </config-file>
+
+        <source-file src="src\wp7\ChildBrowserCommand.cs"
+                     target-dir="Plugins\" />
+
+        <!-- modify the project file to include the added files -->
+        <config-file target=".csproj" parent=".">  
+        </config-file> 
+
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java b/cordova-common/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
new file mode 100644
index 0000000..5263b0c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
new file mode 100644
index 0000000..5263b0c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
@@ -0,0 +1 @@
+foo

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
new file mode 100644
index 0000000..6de7b8c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
@@ -0,0 +1 @@
+This is a test file.

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/com.adobe.vars/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/com.adobe.vars/plugin.xml b/cordova-common/spec/fixtures/plugins/com.adobe.vars/plugin.xml
new file mode 100644
index 0000000..9eff729
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/com.adobe.vars/plugin.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="com.adobe.vars"
+    version="3.0.0">
+
+    <name>Use Variables</name>
+
+    <preference name="API_KEY" />
+
+    <info>Remember that your api key is $API_KEY!</info>
+    <!-- android -->
+    <platform name="android">
+		<config-file target="AndroidManifest.xml" parent="/manifest">
+            <poop name="GoogleMapsApiKey" value="$API_KEY" />
+            <package>$PACKAGE_NAME</package>
+		</config-file>
+		
+    </platform>
+    
+    <!-- amazon fireos -->
+    <platform name="amazon-fireos">
+		<config-file target="AndroidManifest.xml" parent="/manifest">
+            <poop name="GoogleMapsApiKey" value="$API_KEY" />
+            <package>$PACKAGE_NAME</package>
+		</config-file>
+		
+    </platform>
+
+    <!-- ios -->
+    <platform name="ios">
+        <config-file target="config.xml" parent="/widget">
+            <awesome value="$API_KEY" />
+            <cfbundleid>$PACKAGE_NAME</cfbundleid>
+        </config-file>
+        <config-file target="*-Info.plist" parent="APluginNode">
+            <string></string>
+        </config-file>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.apache.plist/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.apache.plist/plugin.xml b/cordova-common/spec/fixtures/plugins/org.apache.plist/plugin.xml
new file mode 100644
index 0000000..b7d5439
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.apache.plist/plugin.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.apache.plist"
+    version="3.0.0">
+
+    <name>PList updates</name>
+
+    <!-- ios -->
+    <platform name="ios">
+        <config-file target="*-Info.plist" parent="CFBundleIcons">
+        <dict>
+        <key>UINewsstandIcon</key>
+        <dict>
+        <key>CFBundleIconFiles</key>
+        <array>
+            <string>Newsstand-Cover-Icon.png</string>
+            <string>Newsstand-Cover-Icon@2x.png</string>
+        </array>
+        <key>UINewsstandBindingType</key>
+        <string>UINewsstandBindingTypeMagazine</string>
+        <key>UINewsstandBindingEdge</key>
+        <string>UINewsstandBindingEdgeLeft</string>
+        </dict>
+        </dict>
+        </config-file>
+
+        <config-file target="*-Info.plist" parent="CFValidSchemas">
+        <array>
+            <string>schema-a</string>
+            <string>schema-b</string>
+        </array>
+        </config-file>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.configtest/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.configtest/plugin.xml b/cordova-common/spec/fixtures/plugins/org.test.configtest/plugin.xml
new file mode 100644
index 0000000..fa1ff51
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.configtest/plugin.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.configtest"
+    version="3.0.0">
+
+    <name>Does Code Fil Write Even Work? Hopefully the Tests Will Tell Us</name>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="/widget">
+            <poop/>
+        </config-file>
+        <config-file target="res/xml/config.xml" parent="/widget">
+            <poop/>
+        </config-file>
+    </platform>
+
+    <platform name="windows">
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities">
+            <Capability Note="should-exist-for-all-appxmanifest-target-files" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions="<=8.0.0">
+            <Capability Note="should-exist-for-win8-only" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions="=8.1.0">
+            <Capability Note="should-exist-for-win81-win-and-phone" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions="<=8.1.0" device-target="windows">
+            <Capability Note="should-exist-for-win8-and-win81-win-only" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions="<=8.1.0" device-target="phone">
+            <Capability Note="should-exist-for-win81-phone-only" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions="<=8.1.0" device-target="all">
+            <Capability Note="should-exist-for-win8-and-win81-both" />
+        </config-file>
+        <config-file target="package.appxmanifest" parent="/Parent/Capabilities" versions=">=10.0.0">
+            <Capability Note="should-exist-in-win10-only" />
+        </config-file>
+    </platform>
+</plugin>


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


[02/10] cordova-lib git commit: CB-9598 Initial implementation for cordova-common module

Posted by sg...@apache.org.
CB-9598 Initial implementation for cordova-common module


Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/28ce0d1d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/28ce0d1d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/28ce0d1d

Branch: refs/heads/master
Commit: 28ce0d1d8665caff4977622f6b178b7f4899896e
Parents: 436679f
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Wed Sep 16 18:17:24 2015 +0300
Committer: sgrebnov <v-...@microsoft.com>
Committed: Sun Sep 20 15:14:53 2015 +0300

----------------------------------------------------------------------
 cordova-common/.jscs.json                       |  24 +
 cordova-common/.jshintignore                    |   1 +
 cordova-common/.npmignore                       |   2 +
 cordova-common/.ratignore                       |   2 +
 cordova-common/README.md                        |  33 ++
 cordova-common/RELEASENOTES.md                  |  24 +
 cordova-common/cordova-common.js                |  41 ++
 cordova-common/package.json                     |  46 ++
 cordova-common/spec/.jshintrc                   |  11 +
 cordova-common/spec/ConfigParser.spec.js        | 224 +++++++++
 cordova-common/src/.jshintrc                    |  10 +
 cordova-common/src/ActionStack.js               |  85 ++++
 .../src/ConfigChanges/ConfigChanges.js          | 401 ++++++++++++++++
 cordova-common/src/ConfigChanges/ConfigFile.js  | 220 +++++++++
 .../src/ConfigChanges/ConfigKeeper.js           |  65 +++
 cordova-common/src/ConfigChanges/munge-util.js  | 160 +++++++
 cordova-common/src/CordovaError.js              |  32 ++
 cordova-common/src/PlatformJson.js              | 155 ++++++
 cordova-common/src/PluginInfo/PluginInfo.js     | 416 ++++++++++++++++
 .../src/PluginInfo/PluginInfoProvider.js        |  82 ++++
 cordova-common/src/configparser/ConfigParser.js | 470 +++++++++++++++++++
 cordova-common/src/configparser/README.md       |  86 ++++
 cordova-common/src/events.js                    |  19 +
 cordova-common/src/superspawn.js                | 154 ++++++
 cordova-common/src/util/plist-helpers.js        | 101 ++++
 cordova-common/src/util/xml-helpers.js          | 266 +++++++++++
 26 files changed, 3130 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/.jscs.json
----------------------------------------------------------------------
diff --git a/cordova-common/.jscs.json b/cordova-common/.jscs.json
new file mode 100644
index 0000000..5cc7e26
--- /dev/null
+++ b/cordova-common/.jscs.json
@@ -0,0 +1,24 @@
+{
+    "disallowMixedSpacesAndTabs": true,
+    "disallowTrailingWhitespace": true,
+    "validateLineBreaks": "LF",
+    "validateIndentation": 4,
+    "requireLineFeedAtFileEnd": true,
+
+    "disallowSpaceAfterPrefixUnaryOperators": true,
+    "disallowSpaceBeforePostfixUnaryOperators": true,
+    "requireSpaceAfterLineComment": true,
+    "requireCapitalizedConstructors": true,
+
+    "disallowSpacesInNamedFunctionExpression": {
+        "beforeOpeningRoundBrace": true
+    },
+
+    "requireSpaceAfterKeywords": [
+      "if",
+      "else",
+      "for",
+      "while",
+      "do"
+    ]
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/.jshintignore
----------------------------------------------------------------------
diff --git a/cordova-common/.jshintignore b/cordova-common/.jshintignore
new file mode 100644
index 0000000..d606f61
--- /dev/null
+++ b/cordova-common/.jshintignore
@@ -0,0 +1 @@
+spec/fixtures/*

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/.npmignore
----------------------------------------------------------------------
diff --git a/cordova-common/.npmignore b/cordova-common/.npmignore
new file mode 100644
index 0000000..5d14118
--- /dev/null
+++ b/cordova-common/.npmignore
@@ -0,0 +1,2 @@
+spec
+coverage

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/.ratignore
----------------------------------------------------------------------
diff --git a/cordova-common/.ratignore b/cordova-common/.ratignore
new file mode 100644
index 0000000..26f7205
--- /dev/null
+++ b/cordova-common/.ratignore
@@ -0,0 +1,2 @@
+fixtures
+coverage

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/README.md
----------------------------------------------------------------------
diff --git a/cordova-common/README.md b/cordova-common/README.md
new file mode 100644
index 0000000..13dba33
--- /dev/null
+++ b/cordova-common/README.md
@@ -0,0 +1,33 @@
+<!--
+#
+# 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.
+#
+-->
+
+# cordova-lib
+Contains shared classes and routines used by [cordova-lib](https://github.com/apache/cordova-lib/) and platforms.
+
+## Setup
+* Clone this repository onto your local machine. 
+    `git clone https://git-wip-us.apache.org/repos/asf/cordova-lib.git`
+* In terminal, navigate to the inner cordova-common directory.
+    `cd cordova-lib/cordova-common`
+* Install dependencies and npm-link
+    `npm install && npm link`
+* Navigate to cordova-lib directory and link cordova-common
+    `cd ../cordova-lib && npm link cordova-common && npm install`

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/RELEASENOTES.md
----------------------------------------------------------------------
diff --git a/cordova-common/RELEASENOTES.md b/cordova-common/RELEASENOTES.md
new file mode 100644
index 0000000..0541a9e
--- /dev/null
+++ b/cordova-common/RELEASENOTES.md
@@ -0,0 +1,24 @@
+<!--
+#
+# 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.
+#
+-->
+# Cordova-lib Release Notes
+
+### 0.1.0 (Aug 25, 2015)
+* Initial release

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/cordova-common.js
----------------------------------------------------------------------
diff --git a/cordova-common/cordova-common.js b/cordova-common/cordova-common.js
new file mode 100644
index 0000000..5873aa7
--- /dev/null
+++ b/cordova-common/cordova-common.js
@@ -0,0 +1,41 @@
+/**
+    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.
+*/
+
+/* jshint node:true */
+
+// For now expose plugman and cordova just as they were in the old repos
+exports = module.exports = {
+    events: require('./src/events'),
+    superspawn: require('./src/superspawn'),
+
+    ActionStack: require('./src/ActionStack'),
+    CordovaError: require('./src/CordovaError'),
+    PlatformJson: require('./src/PlatformJson'),
+    ConfigParser: require('./src/ConfigParser/ConfigParser.js'),
+
+    PluginInfo: require('./src/PluginInfo/PluginInfo.js'),
+    PluginInfoProvider: require('./src/PluginInfo/PluginInfoProvider.js'),
+
+    ConfigChanges: require('./src/ConfigChanges/ConfigChanges.js'),
+    ConfigKeeper: require('./src/ConfigChanges/ConfigKeeper.js'),
+    ConfigFile: require('./src/ConfigChanges/ConfigFile.js'),
+    mungeUtil: require('./src/ConfigChanges/munge-util.js'),
+
+    xmlHelpers: require('./src/util/xml-helpers')
+};

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/package.json
----------------------------------------------------------------------
diff --git a/cordova-common/package.json b/cordova-common/package.json
new file mode 100644
index 0000000..525e951
--- /dev/null
+++ b/cordova-common/package.json
@@ -0,0 +1,46 @@
+{
+  "author": "Apache Software Foundation",
+  "name": "cordova-common",
+  "description": "Apache Cordova tools and platforms shared routines",
+  "license": "Apache-2.0",
+  "version": "0.1.0",
+  "repository": {
+    "type": "git",
+    "url": "git://git-wip-us.apache.org/repos/asf/cordova-common.git"
+  },
+  "bugs": {
+    "url": "https://issues.apache.org/jira/browse/CB",
+    "email": "dev@cordova.apache.org"
+  },
+  "main": "cordova-common.js",
+  "engines": {
+    "node": ">=0.9.9"
+  },
+  "scripts": {
+    "test": "npm run jshint && npm run jasmine",
+    "jshint": "node node_modules/jshint/bin/jshint src && node node_modules/jshint/bin/jshint spec",
+    "jasmine": "node node_modules/jasmine-node/bin/jasmine-node --captureExceptions --color spec",
+    "cover": "node node_modules/istanbul/lib/cli.js cover --root src --print detail node_modules/jasmine-node/bin/jasmine-node -- spec"
+  },
+  "engineStrict": true,
+  "dependencies": {
+    "bplist-parser": "^0.1.0",
+    "cordova-registry-mapper": "^1.1.8",
+    "elementtree": "^0.1.6",
+    "glob": "^5.0.13",
+    "osenv": "^0.1.3",
+    "plist": "^1.1.0",
+    "q": "^1.4.1",
+    "semver": "^5.0.1",
+    "shelljs": "^0.5.1",
+    "underscore": "^1.8.3",
+    "unorm": "^1.3.3",
+    "xcode": "^0.8.0"
+  },
+  "devDependencies": {
+    "istanbul": "^0.3.17",
+    "jasmine-node": "^1.14.5",
+    "jshint": "^2.8.0"
+  },
+  "contributors": []
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/spec/.jshintrc
----------------------------------------------------------------------
diff --git a/cordova-common/spec/.jshintrc b/cordova-common/spec/.jshintrc
new file mode 100644
index 0000000..17eae32
--- /dev/null
+++ b/cordova-common/spec/.jshintrc
@@ -0,0 +1,11 @@
+{
+    "node": true
+  , "bitwise": true
+  , "undef": true
+  , "trailing": true
+  , "quotmark": true
+  , "indent": 4
+  , "unused": "vars"
+  , "latedef": "nofunc"
+  , "jasmine": true
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/spec/ConfigParser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/ConfigParser.spec.js b/cordova-common/spec/ConfigParser.spec.js
new file mode 100644
index 0000000..a888cf4
--- /dev/null
+++ b/cordova-common/spec/ConfigParser.spec.js
@@ -0,0 +1,224 @@
+/**
+    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 path = require('path'),
+    fs = require('fs'),
+    ConfigParser = require('../src/configparser/ConfigParser'),
+    xml = path.join(__dirname, 'test-config.xml'),
+    xml_contents = fs.readFileSync(xml, 'utf-8');
+
+describe('config.xml parser', function () {
+    var readFile;
+    beforeEach(function() {
+        readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
+    });
+
+    it('should create an instance based on an xml file', function() {
+        var cfg;
+        expect(function () {
+            cfg = new ConfigParser(xml);
+        }).not.toThrow();
+        expect(cfg).toBeDefined();
+        expect(cfg.doc).toBeDefined();
+    });
+
+    describe('methods', function() {
+        var cfg;
+        beforeEach(function() {
+            cfg = new ConfigParser(xml);
+        });
+
+        describe('package name / id', function() {
+            it('should get the (default) packagename', function() {
+                expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
+            });
+            it('should allow setting the packagename', function() {
+                cfg.setPackageName('this.is.bat.country');
+                expect(cfg.packageName()).toEqual('this.is.bat.country');
+            });
+        });
+
+        describe('package name / android-packageName', function() {
+            it('should get the android packagename', function() {
+                expect(cfg.android_packageName()).toEqual('io.cordova.hellocordova.android');
+            });
+        });
+
+        describe('package name / ios-CFBundleIdentifier', function() {
+            it('should get the ios packagename', function() {
+                expect(cfg.ios_CFBundleIdentifier()).toEqual('io.cordova.hellocordova.ios');
+            });
+        });
+
+        describe('version', function() {
+            it('should get the version', function() {
+                expect(cfg.version()).toEqual('0.0.1');
+            });
+            it('should allow setting the version', function() {
+                cfg.setVersion('2.0.1');
+                expect(cfg.version()).toEqual('2.0.1');
+            });
+        });
+
+        describe('app name', function() {
+            it('should get the (default) app name', function() {
+                expect(cfg.name()).toEqual('Hello Cordova');
+            });
+            it('should allow setting the app name', function() {
+                cfg.setName('this.is.bat.country');
+                expect(cfg.name()).toEqual('this.is.bat.country');
+            });
+        });
+        describe('preference', function() {
+            it('should return the value of a global preference', function() {
+                expect(cfg.getPreference('fullscreen')).toEqual('true');
+            });
+            it('should return the value of a platform-specific preference', function() {
+                expect(cfg.getPreference('android-minSdkVersion', 'android')).toEqual('10');
+            });
+            it('should return an empty string for a non-existing preference', function() {
+                expect(cfg.getPreference('zimzooo!')).toEqual('');
+            });
+        });
+        describe('global preference', function() {
+            it('should return the value of a global preference', function() {
+                expect(cfg.getGlobalPreference('orientation')).toEqual('portrait');
+            });
+            it('should return an empty string for a non-existing preference', function() {
+                expect(cfg.getGlobalPreference('foobar')).toEqual('');
+            });
+        });
+        describe('platform-specific preference', function() {
+            it('should return the value of a platform specific preference', function() {
+                expect(cfg.getPlatformPreference('orientation', 'android')).toEqual('landscape');
+            });
+            it('should return an empty string when querying for a non-existing preference', function() {
+                expect(cfg.getPlatformPreference('foobar', 'android')).toEqual('');
+            });
+            it('should return an empty string when querying with unsupported platform', function() {
+                expect(cfg.getPlatformPreference('orientation', 'foobar')).toEqual('');
+            });
+        });
+        describe('plugin',function(){
+            it('should read plugin id list', function() {
+               var expectedList = [
+                   'org.apache.cordova.pluginwithvars',
+                   'org.apache.cordova.pluginwithurl',
+                   'org.apache.cordova.pluginwithversion',
+                   'org.apache.cordova.pluginwithurlandversion',
+                   'org.apache.cordova.justaplugin',
+                   'org.apache.cordova.legacyfeatureversion',
+                   'org.apache.cordova.legacyfeatureurl',
+                   'org.apache.cordova.legacyfeatureversionandurl'
+               ];
+               var list = cfg.getPluginIdList();
+               expect(list.length).toEqual(expectedList.length);
+               expectedList.forEach(function(plugin){
+                   expect(list).toContain(plugin);
+               });
+            });
+            it('should read plugin given id', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.justaplugin');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.justaplugin');
+                expect(plugin.variables).toBeDefined();
+            });
+            it('should not read plugin given undefined id', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.undefinedplugin');
+                expect(plugin).not.toBeDefined();
+            });
+            it('should read plugin with src and store it in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurl');
+            });
+            it('should read plugin with version and store it in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithversion');
+                expect(plugin.spec).toEqual('1.1.1');
+            });
+            it('should read plugin with source and version and store source in spec field', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithurlandversion');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/pluginwithurlandversion');
+            });
+            it('should read plugin variables', function () {
+                var plugin = cfg.getPlugin('org.apache.cordova.pluginwithvars');
+                expect(plugin.variables).toBeDefined();
+                expect(plugin.variables.var).toBeDefined();
+                expect(plugin.variables.var).toEqual('varvalue');
+            });
+            it('should allow adding a new plugin', function(){
+                cfg.addPlugin({name:'myplugin'});
+                var plugins = cfg.doc.findall('plugin');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).toContain('myplugin');
+            });
+            it('should allow adding features with params', function(){
+                cfg.addPlugin({name:'aplugin'}, [{name:'paraname',value:'paravalue'}]);
+                // Additional check for new parameters syntax
+                cfg.addPlugin({name:'bplugin'}, {paraname: 'paravalue'});
+                var plugins = cfg.doc.findall('plugin')
+                .filter(function (plugin) {
+                    return plugin.attrib.name === 'aplugin' || plugin.attrib.name === 'bplugin';
+                });
+                expect(plugins.length).toBe(2);
+                plugins.forEach(function (plugin) {
+                    var variables = plugin.findall('variable');
+                    expect(variables[0].attrib.name).toEqual('paraname');
+                    expect(variables[0].attrib.value).toEqual('paravalue');
+                });
+            });
+            it('should be able to read legacy feature entries with a version', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversion');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversion');
+                expect(plugin.spec).toEqual('1.2.3');
+                expect(plugin.variables).toBeDefined();
+                expect(plugin.variables.aVar).toEqual('aValue');
+            });
+            it('should be able to read legacy feature entries with a url', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureurl');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureurl');
+            });
+            it('should be able to read legacy feature entries with a version and a url', function(){
+                var plugin = cfg.getPlugin('org.apache.cordova.legacyfeatureversionandurl');
+                expect(plugin).toBeDefined();
+                expect(plugin.name).toEqual('org.apache.cordova.legacyfeatureversionandurl');
+                expect(plugin.spec).toEqual('http://cordova.apache.org/legacyfeatureversionandurl');
+            });
+            it('it should remove given plugin', function(){
+                cfg.removePlugin('org.apache.cordova.justaplugin');
+                var plugins = cfg.doc.findall('plugin');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).not.toContain('org.apache.cordova.justaplugin');
+            });
+            it('it should remove given legacy feature id', function(){
+                cfg.removePlugin('org.apache.cordova.legacyplugin');
+                var plugins = cfg.doc.findall('feature');
+                var pluginNames = plugins.map(function(plugin){
+                    return plugin.attrib.name;
+                });
+                expect(pluginNames).not.toContain('org.apache.cordova.legacyplugin');
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/.jshintrc
----------------------------------------------------------------------
diff --git a/cordova-common/src/.jshintrc b/cordova-common/src/.jshintrc
new file mode 100644
index 0000000..89a121c
--- /dev/null
+++ b/cordova-common/src/.jshintrc
@@ -0,0 +1,10 @@
+{
+    "node": true
+  , "bitwise": true
+  , "undef": true
+  , "trailing": true
+  , "quotmark": true
+  , "indent": 4
+  , "unused": "vars"
+  , "latedef": "nofunc"
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/ActionStack.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ActionStack.js b/cordova-common/src/ActionStack.js
new file mode 100644
index 0000000..5ef6f84
--- /dev/null
+++ b/cordova-common/src/ActionStack.js
@@ -0,0 +1,85 @@
+/**
+    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.
+*/
+
+/* jshint quotmark:false */
+
+var events = require('./events'),
+    Q = require('q');
+
+function ActionStack() {
+    this.stack = [];
+    this.completed = [];
+}
+
+ActionStack.prototype = {
+    createAction:function(handler, action_params, reverter, revert_params) {
+        return {
+            handler:{
+                run:handler,
+                params:action_params
+            },
+            reverter:{
+                run:reverter,
+                params:revert_params
+            }
+        };
+    },
+    push:function(tx) {
+        this.stack.push(tx);
+    },
+    // Returns a promise.
+    process:function(platform) {
+        events.emit('verbose', 'Beginning processing of action stack for ' + platform + ' project...');
+
+        while (this.stack.length) {
+            var action = this.stack.shift();
+            var handler = action.handler.run;
+            var action_params = action.handler.params;
+
+            try {
+                handler.apply(null, action_params);
+            } catch(e) {
+                events.emit('warn', 'Error during processing of action! Attempting to revert...');
+                this.stack.unshift(action);
+                var issue = 'Uh oh!\n';
+                // revert completed tasks
+                while(this.completed.length) {
+                    var undo = this.completed.shift();
+                    var revert = undo.reverter.run;
+                    var revert_params = undo.reverter.params;
+
+                    try {
+                        revert.apply(null, revert_params);
+                    } catch(err) {
+                        events.emit('warn', 'Error during reversion of action! We probably really messed up your project now, sorry! D:');
+                        issue += 'A reversion action failed: ' + err.message + '\n';
+                    }
+                }
+                e.message = issue + e.message;
+                return Q.reject(e);
+            }
+            this.completed.push(action);
+        }
+        events.emit('verbose', 'Action stack processing complete.');
+
+        return Q();
+    }
+};
+
+module.exports = ActionStack;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/ConfigChanges/ConfigChanges.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ConfigChanges/ConfigChanges.js b/cordova-common/src/ConfigChanges/ConfigChanges.js
new file mode 100644
index 0000000..8175ae7
--- /dev/null
+++ b/cordova-common/src/ConfigChanges/ConfigChanges.js
@@ -0,0 +1,401 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * 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.
+ *
+*/
+
+/*
+ * This module deals with shared configuration / dependency "stuff". That is:
+ * - XML configuration files such as config.xml, AndroidManifest.xml or WMAppManifest.xml.
+ * - plist files in iOS
+ * - pbxproj files in iOS
+ * Essentially, any type of shared resources that we need to handle with awareness
+ * of how potentially multiple plugins depend on a single shared resource, should be
+ * handled in this module.
+ *
+ * The implementation uses an object as a hash table, with "leaves" of the table tracking
+ * reference counts.
+ */
+
+/* jshint sub:true */
+
+var fs   = require('fs'),
+    path = require('path'),
+    et   = require('elementtree'),
+    semver = require('semver'),
+    events = require('../events'),
+    ConfigKeeper = require('./ConfigKeeper');
+
+var mungeutil = require('./munge-util');
+
+
+// These frameworks are required by cordova-ios by default. We should never add/remove them.
+var keep_these_frameworks = [
+    'MobileCoreServices.framework',
+    'CoreGraphics.framework',
+    'AssetsLibrary.framework'
+];
+
+
+exports.PlatformMunger = PlatformMunger;
+
+exports.process = function(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider) {
+    var munger = new PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider);
+    munger.process(plugins_dir);
+    munger.save_all();
+};
+
+/******************************************************************************
+* PlatformMunger class
+*
+* Can deal with config file of a single project.
+* Parsed config files are cached in a ConfigKeeper object.
+******************************************************************************/
+function PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider) {
+    this.platform = platform;
+    this.project_dir = project_dir;
+    this.config_keeper = new ConfigKeeper(project_dir);
+    this.platformJson = platformJson;
+    this.pluginInfoProvider = pluginInfoProvider;
+}
+
+// Write out all unsaved files.
+PlatformMunger.prototype.save_all = PlatformMunger_save_all;
+function PlatformMunger_save_all() {
+    this.config_keeper.save_all();
+    this.platformJson.save();
+}
+
+// Apply a munge object to a single config file.
+// The remove parameter tells whether to add the change or remove it.
+PlatformMunger.prototype.apply_file_munge = PlatformMunger_apply_file_munge;
+function PlatformMunger_apply_file_munge(file, munge, remove) {
+    var self = this;
+    var xml_child;
+
+    if ( file === 'framework' && self.platform === 'ios' ) {
+        // ios pbxproj file
+        var pbxproj = self.config_keeper.get(self.project_dir, self.platform, 'framework');
+        // CoreLocation dependency removed in cordova-ios@3.6.0.
+        var keepFrameworks = keep_these_frameworks;
+        if (semver.lt(pbxproj.cordovaVersion, '3.6.0-dev')) {
+            keepFrameworks = keepFrameworks.concat(['CoreLocation.framework']);
+        }
+        for (var src in munge.parents) {
+            for (xml_child in munge.parents[src]) {
+                var weak = munge.parents[src][xml_child].xml;
+                // Only add the framework if it's not a cordova-ios core framework
+                if (keep_these_frameworks.indexOf(src) == -1) {
+                    // xml_child in this case is whether the framework should use weak or not
+                    if (remove) {
+                        pbxproj.data.removeFramework(src);
+                    } else {
+                        pbxproj.data.addFramework(src, {weak: weak});
+                    }
+                    pbxproj.is_changed = true;
+                }
+            }
+        }
+    } else {
+        // all other types of files
+        for (var selector in munge.parents) {
+            for (xml_child in munge.parents[selector]) {
+                // this xml child is new, graft it (only if config file exists)
+                var config_file = self.config_keeper.get(self.project_dir, self.platform, file);
+                if (config_file.exists) {
+                    if (remove) config_file.prune_child(selector, munge.parents[selector][xml_child]);
+                    else config_file.graft_child(selector, munge.parents[selector][xml_child]);
+                }
+            }
+        }
+    }
+}
+
+
+PlatformMunger.prototype.remove_plugin_changes = remove_plugin_changes;
+function remove_plugin_changes(pluginInfo, is_top_level) {
+    var self = this;
+    var platform_config = self.platformJson.root;
+    var plugin_vars = is_top_level ?
+        platform_config.installed_plugins[pluginInfo.id] :
+        platform_config.dependent_plugins[pluginInfo.id];
+
+    // get config munge, aka how did this plugin change various config files
+    var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
+    // global munge looks at all plugins' changes to config files
+    var global_munge = platform_config.config_munge;
+    var munge = mungeutil.decrement_munge(global_munge, config_munge);
+
+    for (var file in munge.files) {
+        if (file == 'plugins-plist' && self.platform == 'ios') {
+            // TODO: remove this check and <plugins-plist> sections in spec/plugins/../plugin.xml files.
+            events.emit(
+                'warn',
+                'WARNING: Plugin "' + pluginInfo.id + '" uses <plugins-plist> element(s), ' +
+                'which are no longer supported. Support has been removed as of Cordova 3.4.'
+            );
+            continue;
+        }
+        // CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
+        if (self.platform == 'windows' && file == 'package.appxmanifest' &&
+            !fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
+            // New windows template separate manifest files for Windows8, Windows8.1 and WP8.1
+            var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows80.appxmanifest', 'package.windows10.appxmanifest'];
+            /* jshint loopfunc:true */
+            substs.forEach(function(subst) {
+                events.emit('verbose', 'Applying munge to ' + subst);
+                self.apply_file_munge(subst, munge.files[file], true);
+            });
+            /* jshint loopfunc:false */
+        }
+        self.apply_file_munge(file, munge.files[file], /* remove = */ true);
+    }
+
+    // Remove from installed_plugins
+    self.platformJson.removePlugin(pluginInfo.id, is_top_level);
+    return self;
+}
+
+
+PlatformMunger.prototype.add_plugin_changes = add_plugin_changes;
+function add_plugin_changes(pluginInfo, plugin_vars, is_top_level, should_increment) {
+    var self = this;
+    var platform_config = self.platformJson.root;
+
+    // get config munge, aka how should this plugin change various config files
+    var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
+    // global munge looks at all plugins' changes to config files
+
+    // TODO: The should_increment param is only used by cordova-cli and is going away soon.
+    // If should_increment is set to false, avoid modifying the global_munge (use clone)
+    // and apply the entire config_munge because it's already a proper subset of the global_munge.
+    var munge, global_munge;
+    if (should_increment) {
+        global_munge = platform_config.config_munge;
+        munge = mungeutil.increment_munge(global_munge, config_munge);
+    } else {
+        global_munge = mungeutil.clone_munge(platform_config.config_munge);
+        munge = config_munge;
+    }
+
+    for (var file in munge.files) {
+        // TODO: remove this warning some time after 3.4 is out.
+        if (file == 'plugins-plist' && self.platform == 'ios') {
+            events.emit(
+                'warn',
+                'WARNING: Plugin "' + pluginInfo.id + '" uses <plugins-plist> element(s), ' +
+                'which are no longer supported. Support has been removed as of Cordova 3.4.'
+            );
+            continue;
+        }
+        // CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
+        if (self.platform == 'windows' && file == 'package.appxmanifest' &&
+            !fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
+            var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows80.appxmanifest', 'package.windows10.appxmanifest'];
+            /* jshint loopfunc:true */
+            substs.forEach(function(subst) {
+                events.emit('verbose', 'Applying munge to ' + subst);
+                self.apply_file_munge(subst, munge.files[file]);
+            });
+            /* jshint loopfunc:false */
+        }
+        self.apply_file_munge(file, munge.files[file]);
+    }
+
+    // Move to installed/dependent_plugins
+    self.platformJson.addPlugin(pluginInfo.id, plugin_vars || {}, is_top_level);
+    return self;
+}
+
+
+// Load the global munge from platform json and apply all of it.
+// Used by cordova prepare to re-generate some config file from platform
+// defaults and the global munge.
+PlatformMunger.prototype.reapply_global_munge = reapply_global_munge ;
+function reapply_global_munge () {
+    var self = this;
+
+    var platform_config = self.platformJson.root;
+    var global_munge = platform_config.config_munge;
+    for (var file in global_munge.files) {
+        // TODO: remove this warning some time after 3.4 is out.
+        if (file == 'plugins-plist' && self.platform == 'ios') {
+            events.emit(
+                'warn',
+                'WARNING: One of your plugins uses <plugins-plist> element(s), ' +
+                'which are no longer supported. Support has been removed as of Cordova 3.4.'
+            );
+            continue;
+        }
+
+        self.apply_file_munge(file, global_munge.files[file]);
+    }
+
+    return self;
+}
+
+
+// generate_plugin_config_munge
+// Generate the munge object from plugin.xml + vars
+PlatformMunger.prototype.generate_plugin_config_munge = generate_plugin_config_munge;
+function generate_plugin_config_munge(pluginInfo, vars) {
+    var self = this;
+
+    vars = vars || {};
+    var munge = { files: {} };
+    var changes = pluginInfo.getConfigFiles(self.platform);
+
+    // note down pbxproj framework munges in special section of munge obj
+    // CB-5238 this is only for systems frameworks
+    if (self.platform === 'ios') {
+        var frameworks = pluginInfo.getFrameworks(self.platform);
+        frameworks.forEach(function (f) {
+            if (!f.custom) {
+                mungeutil.deep_add(munge, 'framework', f.src, { xml: f.weak, count: 1 });
+            }
+        });
+    }
+
+    // Demux 'package.appxmanifest' into relevant platform-specific appx manifests.
+    // Only spend the cycles if there are version-specific plugin settings
+    if (self.platform === 'windows' &&
+            changes.some(function(change) {
+                return ((typeof change.versions !== 'undefined') ||
+                    (typeof change.deviceTarget !== 'undefined'));
+            }))
+    {
+        var manifests = {
+            'windows': {
+                '8.0.0': 'package.windows80.appxmanifest',
+                '8.1.0': 'package.windows.appxmanifest',
+                '10.0.0': 'package.windows10.appxmanifest'
+            },
+            'phone': {
+                '8.1.0': 'package.phone.appxmanifest',
+                '10.0.0': 'package.windows10.appxmanifest'
+            },
+            'all': {
+                '8.0.0': 'package.windows80.appxmanifest',
+                '8.1.0': ['package.windows.appxmanifest', 'package.phone.appxmanifest'],
+                '10.0.0': 'package.windows10.appxmanifest'
+            }
+        };
+
+        var oldChanges = changes;
+        changes = [];
+
+        oldChanges.forEach(function(change, changeIndex) {
+            // Only support semver/device-target demux for package.appxmanifest
+            // Pass through in case something downstream wants to use it
+            if (change.target !== 'package.appxmanifest') {
+                changes.push(change);
+                return;
+            }
+
+            var hasVersion = (typeof change.versions !== 'undefined');
+            var hasTargets = (typeof change.deviceTarget !== 'undefined');
+
+            // No semver/device-target for this config-file, pass it through
+            if (!(hasVersion || hasTargets)) {
+                changes.push(change);
+                return;
+            }
+
+            var targetDeviceSet = hasTargets ? change.deviceTarget : 'all';
+            if (['windows', 'phone', 'all'].indexOf(targetDeviceSet) === -1) {
+                // target-device couldn't be resolved, fix it up here to a valid value
+                targetDeviceSet = 'all';
+            }
+            var knownWindowsVersionsForTargetDeviceSet = Object.keys(manifests[targetDeviceSet]);
+
+            // at this point, 'change' targets package.appxmanifest and has a version attribute
+            knownWindowsVersionsForTargetDeviceSet.forEach(function(winver) {
+                // This is a local function that creates the new replacement representing the
+                // mutation.  Used to save code further down.
+                var createReplacement = function(manifestFile, originalChange) {
+                    var replacement = {
+                        target:         manifestFile,
+                        parent:         originalChange.parent,
+                        after:          originalChange.after,
+                        xmls:           originalChange.xmls,
+                        versions:       originalChange.versions,
+                        deviceTarget:   originalChange.deviceTarget
+                    };
+                    return replacement;
+                };
+
+                // version doesn't satisfy, so skip
+                if (hasVersion && !semver.satisfies(winver, change.versions)) {
+                    return;
+                }
+
+                var versionSpecificManifests = manifests[targetDeviceSet][winver];
+                if (versionSpecificManifests.constructor === Array) {
+                    // e.g. all['8.1.0'] === ['pkg.windows.appxmanifest', 'pkg.phone.appxmanifest']
+                    versionSpecificManifests.forEach(function(manifestFile) {
+                        changes.push(createReplacement(manifestFile, change));
+                    });
+                }
+                else {
+                    // versionSpecificManifests is actually a single string
+                    changes.push(createReplacement(versionSpecificManifests, change));
+                }
+            });
+        });
+    }
+
+    changes.forEach(function(change) {
+        change.xmls.forEach(function(xml) {
+            // 1. stringify each xml
+            var stringified = (new et.ElementTree(xml)).write({xml_declaration:false});
+            // interp vars
+            if (vars) {
+                Object.keys(vars).forEach(function(key) {
+                    var regExp = new RegExp('\\$' + key, 'g');
+                    stringified = stringified.replace(regExp, vars[key]);
+                });
+            }
+            // 2. add into munge
+            mungeutil.deep_add(munge, change.target, change.parent, { xml: stringified, count: 1, after: change.after });
+        });
+    });
+    return munge;
+}
+
+// Go over the prepare queue and apply the config munges for each plugin
+// that has been (un)installed.
+PlatformMunger.prototype.process = PlatformMunger_process;
+function PlatformMunger_process(plugins_dir) {
+    var self = this;
+    var platform_config = self.platformJson.root;
+
+    // Uninstallation first
+    platform_config.prepare_queue.uninstalled.forEach(function(u) {
+        var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+        self.remove_plugin_changes(pluginInfo, u.topLevel);
+    });
+
+    // Now handle installation
+    platform_config.prepare_queue.installed.forEach(function(u) {
+        var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+        self.add_plugin_changes(pluginInfo, u.vars, u.topLevel, true);
+    });
+
+    // Empty out installed/ uninstalled queues.
+    platform_config.prepare_queue.uninstalled = [];
+    platform_config.prepare_queue.installed = [];
+}
+/**** END of PlatformMunger ****/

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/ConfigChanges/ConfigFile.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ConfigChanges/ConfigFile.js b/cordova-common/src/ConfigChanges/ConfigFile.js
new file mode 100644
index 0000000..a531e1f
--- /dev/null
+++ b/cordova-common/src/ConfigChanges/ConfigFile.js
@@ -0,0 +1,220 @@
+/*
+ * 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 fs = require('fs');
+var path = require('path');
+
+var bplist = require('bplist-parser');
+var et   = require('elementtree');
+var glob = require('glob');
+var plist = require('plist');
+var xcode = require('xcode');
+
+var plist_helpers = require('../util/plist-helpers');
+var xml_helpers = require('../util/xml-helpers');
+
+/******************************************************************************
+* ConfigFile class
+*
+* Can load and keep various types of config files. Provides some functionality
+* specific to some file types such as grafting XML children. In most cases it
+* should be instantiated by ConfigKeeper.
+*
+* For plugin.xml files use as:
+* plugin_config = self.config_keeper.get(plugin_dir, '', 'plugin.xml');
+*
+* TODO: Consider moving it out to a separate file and maybe partially with
+* overrides in platform handlers.
+******************************************************************************/
+function ConfigFile(project_dir, platform, file_tag) {
+    this.project_dir = project_dir;
+    this.platform = platform;
+    this.file_tag = file_tag;
+    this.is_changed = false;
+
+    this.load();
+}
+
+// ConfigFile.load()
+ConfigFile.prototype.load = ConfigFile_load;
+function ConfigFile_load() {
+    var self = this;
+
+    // config file may be in a place not exactly specified in the target
+    var filepath = self.filepath = resolveConfigFilePath(self.project_dir, self.platform, self.file_tag);
+
+    if ( !filepath || !fs.existsSync(filepath) ) {
+        self.exists = false;
+        return;
+    }
+    self.exists = true;
+    var ext = path.extname(filepath);
+    // Windows8 uses an appxmanifest, and wp8 will likely use
+    // the same in a future release
+    if (ext == '.xml' || ext == '.appxmanifest') {
+        self.type = 'xml';
+        self.data = xml_helpers.parseElementtreeSync(filepath);
+    } else if (ext == '.pbxproj') {
+        self.type = 'pbxproj';
+        self.data = xcode.project(filepath).parseSync();
+        self.cordovaVersion = fs.readFileSync(path.join(self.project_dir, 'CordovaLib', 'VERSION'), 'utf8').trim();
+    } else {
+        // plist file
+        self.type = 'plist';
+        // TODO: isBinaryPlist() reads the file and then parse re-reads it again.
+        //       We always write out text plist, not binary.
+        //       Do we still need to support binary plist?
+        //       If yes, use plist.parseStringSync() and read the file once.
+        self.data = isBinaryPlist(filepath) ?
+                bplist.parseBuffer(fs.readFileSync(filepath)) :
+                plist.parse(fs.readFileSync(filepath, 'utf8'));
+    }
+}
+
+ConfigFile.prototype.save = function ConfigFile_save() {
+    var self = this;
+    if (self.type === 'xml') {
+        fs.writeFileSync(self.filepath, self.data.write({indent: 4}), 'utf-8');
+    } else if (self.type === 'pbxproj') {
+        fs.writeFileSync(self.filepath, self.data.writeSync());
+    } else {
+        // plist
+        var regExp = new RegExp('<string>[ \t\r\n]+?</string>', 'g');
+        fs.writeFileSync(self.filepath, plist.build(self.data).replace(regExp, '<string></string>'));
+    }
+    self.is_changed = false;
+};
+
+ConfigFile.prototype.graft_child = function ConfigFile_graft_child(selector, xml_child) {
+    var self = this;
+    var filepath = self.filepath;
+    var result;
+    if (self.type === 'xml') {
+        var xml_to_graft = [et.XML(xml_child.xml)];
+        result = xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
+        if ( !result) {
+            throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
+        }
+    } else {
+        // plist file
+        result = plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
+        if ( !result ) {
+            throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
+        }
+    }
+    self.is_changed = true;
+};
+
+ConfigFile.prototype.prune_child = function ConfigFile_prune_child(selector, xml_child) {
+    var self = this;
+    var filepath = self.filepath;
+    var result;
+    if (self.type === 'xml') {
+        var xml_to_graft = [et.XML(xml_child.xml)];
+        result = xml_helpers.pruneXML(self.data, xml_to_graft, selector);
+    } else {
+        // plist file
+        result = plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
+    }
+    if (!result) {
+        var err_msg = 'Pruning at selector "' + selector + '" from "' + filepath + '" went bad.';
+        throw new Error(err_msg);
+    }
+    self.is_changed = true;
+};
+
+// Some config-file target attributes are not qualified with a full leading directory, or contain wildcards.
+// Resolve to a real path in this function.
+// TODO: getIOSProjectname is slow because of glob, try to avoid calling it several times per project.
+function resolveConfigFilePath(project_dir, platform, file) {
+    var filepath = path.join(project_dir, file);
+    var matches;
+
+    // .pbxproj file
+    if (file === 'framework') {
+        var proj_name = getIOSProjectname(project_dir);
+        filepath = path.join(project_dir, proj_name + '.xcodeproj', 'project.pbxproj');
+        return filepath;
+    }
+
+    if (file.indexOf('*') > -1) {
+        // handle wildcards in targets using glob.
+        matches = glob.sync(path.join(project_dir, '**', file));
+        if (matches.length) filepath = matches[0];
+
+        // [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
+        if(matches.length > 1 && file.indexOf('-Info.plist')>-1){
+            var plistName =  getIOSProjectname(project_dir)+'-Info.plist';
+            for (var i=0; i < matches.length; i++) {
+                if(matches[i].indexOf(plistName) > -1){
+                    filepath = matches[i];
+                    break;
+                }
+            }
+        }
+        return filepath;
+    }
+
+    // special-case config.xml target that is just "config.xml". This should be resolved to the real location of the file.
+    // TODO: move the logic that contains the locations of config.xml from cordova CLI into plugman.
+    if (file == 'config.xml') {
+        if (platform == 'ubuntu') {
+            filepath = path.join(project_dir, 'config.xml');
+        } else if (platform == 'ios') {
+            var iospath = getIOSProjectname(project_dir);
+            filepath = path.join(project_dir,iospath, 'config.xml');
+        } else if (platform == 'android') {
+            filepath = path.join(project_dir, 'res', 'xml', 'config.xml');
+        } else {
+            matches = glob.sync(path.join(project_dir, '**', 'config.xml'));
+            if (matches.length) filepath = matches[0];
+        }
+        return filepath;
+    }
+
+    // None of the special cases matched, returning project_dir/file.
+    return filepath;
+}
+
+// Find out the real name of an iOS project
+// TODO: glob is slow, need a better way or caching, or avoid using more than once.
+function getIOSProjectname(project_dir) {
+    var matches = glob.sync(path.join(project_dir, '*.xcodeproj'));
+    var iospath;
+    if (matches.length === 1) {
+        iospath = path.basename(matches[0],'.xcodeproj');
+    } else {
+        var msg;
+        if (matches.length === 0) {
+            msg = 'Does not appear to be an xcode project, no xcode project file in ' + project_dir;
+        } else {
+            msg = 'There are multiple *.xcodeproj dirs in ' + project_dir;
+        }
+        throw new Error(msg);
+    }
+    return iospath;
+}
+
+// determine if a plist file is binary
+function isBinaryPlist(filename) {
+    // I wish there was a synchronous way to read only the first 6 bytes of a
+    // file. This is wasteful :/
+    var buf = '' + fs.readFileSync(filename, 'utf8');
+    // binary plists start with a magic header, "bplist"
+    return buf.substring(0, 6) === 'bplist';
+}
+
+module.exports = ConfigFile;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/ConfigChanges/ConfigKeeper.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ConfigChanges/ConfigKeeper.js b/cordova-common/src/ConfigChanges/ConfigKeeper.js
new file mode 100644
index 0000000..894e922
--- /dev/null
+++ b/cordova-common/src/ConfigChanges/ConfigKeeper.js
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+*/
+/* jshint sub:true */
+
+var path = require('path');
+var ConfigFile = require('./ConfigFile');
+
+/******************************************************************************
+* ConfigKeeper class
+*
+* Used to load and store config files to avoid re-parsing and writing them out
+* multiple times.
+*
+* The config files are referred to by a fake path constructed as
+* project_dir/platform/file
+* where file is the name used for the file in config munges.
+******************************************************************************/
+function ConfigKeeper(project_dir, plugins_dir) {
+    this.project_dir = project_dir;
+    this.plugins_dir = plugins_dir;
+    this._cached = {};
+}
+
+ConfigKeeper.prototype.get = function ConfigKeeper_get(project_dir, platform, file) {
+    var self = this;
+
+    // This fixes a bug with older plugins - when specifying config xml instead of res/xml/config.xml
+    // https://issues.apache.org/jira/browse/CB-6414
+    if(file == 'config.xml' && platform == 'android'){
+        file = 'res/xml/config.xml';
+    }
+    var fake_path = path.join(project_dir, platform, file);
+
+    if (self._cached[fake_path]) {
+        return self._cached[fake_path];
+    }
+    // File was not cached, need to load.
+    var config_file = new ConfigFile(project_dir, platform, file);
+    self._cached[fake_path] = config_file;
+    return config_file;
+};
+
+
+ConfigKeeper.prototype.save_all = function ConfigKeeper_save_all() {
+    var self = this;
+    Object.keys(self._cached).forEach(function (fake_path) {
+        var config_file = self._cached[fake_path];
+        if (config_file.is_changed) config_file.save();
+    });
+};
+
+module.exports = ConfigKeeper;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/ConfigChanges/munge-util.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/ConfigChanges/munge-util.js b/cordova-common/src/ConfigChanges/munge-util.js
new file mode 100644
index 0000000..307b3c1
--- /dev/null
+++ b/cordova-common/src/ConfigChanges/munge-util.js
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ *
+*/
+/* jshint sub:true  */
+
+var _ = require('underscore');
+
+// add the count of [key1][key2]...[keyN] to obj
+// return true if it didn't exist before
+exports.deep_add = function deep_add(obj, keys /* or key1, key2 .... */ ) {
+    if ( !Array.isArray(keys) ) {
+        keys = Array.prototype.slice.call(arguments, 1);
+    }
+
+    return exports.process_munge(obj, true/*createParents*/, function (parentArray, k) {
+        var found = _.find(parentArray, function(element) {
+            return element.xml == k.xml;
+        });
+        if (found) {
+            found.after = found.after || k.after;
+            found.count += k.count;
+        } else {
+            parentArray.push(k);
+        }
+        return !found;
+    }, keys);
+};
+
+// decrement the count of [key1][key2]...[keyN] from obj and remove if it reaches 0
+// return true if it was removed or not found
+exports.deep_remove = function deep_remove(obj, keys /* or key1, key2 .... */ ) {
+    if ( !Array.isArray(keys) ) {
+        keys = Array.prototype.slice.call(arguments, 1);
+    }
+
+    var result = exports.process_munge(obj, false/*createParents*/, function (parentArray, k) {
+        var index = -1;
+        var found = _.find(parentArray, function (element) {
+            index++;
+            return element.xml == k.xml;
+        });
+        if (found) {
+            found.count -= k.count;
+            if (found.count > 0) {
+                return false;
+            }
+            else {
+                parentArray.splice(index, 1);
+            }
+        }
+        return undefined;
+    }, keys);
+
+    return typeof result === 'undefined' ? true : result;
+};
+
+// search for [key1][key2]...[keyN]
+// return the object or undefined if not found
+exports.deep_find = function deep_find(obj, keys /* or key1, key2 .... */ ) {
+    if ( !Array.isArray(keys) ) {
+        keys = Array.prototype.slice.call(arguments, 1);
+    }
+
+    return exports.process_munge(obj, false/*createParents?*/, function (parentArray, k) {
+        return _.find(parentArray, function (element) {
+            return element.xml == (k.xml || k);
+        });
+    }, keys);
+};
+
+// Execute func passing it the parent array and the xmlChild key.
+// When createParents is true, add the file and parent items  they are missing
+// When createParents is false, stop and return undefined if the file and/or parent items are missing
+
+exports.process_munge = function process_munge(obj, createParents, func, keys /* or key1, key2 .... */ ) {
+    if ( !Array.isArray(keys) ) {
+        keys = Array.prototype.slice.call(arguments, 1);
+    }
+    var k = keys[0];
+    if (keys.length == 1) {
+        return func(obj, k);
+    } else if (keys.length == 2) {
+        if (!obj.parents[k] && !createParents) {
+            return undefined;
+        }
+        obj.parents[k] = obj.parents[k] || [];
+        return exports.process_munge(obj.parents[k], createParents, func, keys.slice(1));
+    } else if (keys.length == 3){
+        if (!obj.files[k] && !createParents) {
+            return undefined;
+        }
+        obj.files[k] = obj.files[k] || { parents: {} };
+        return exports.process_munge(obj.files[k], createParents, func, keys.slice(1));
+    } else {
+        throw new Error('Invalid key format. Must contain at most 3 elements (file, parent, xmlChild).');
+    }
+};
+
+// All values from munge are added to base as
+// base[file][selector][child] += munge[file][selector][child]
+// Returns a munge object containing values that exist in munge
+// but not in base.
+exports.increment_munge = function increment_munge(base, munge) {
+    var diff = { files: {} };
+
+    for (var file in munge.files) {
+        for (var selector in munge.files[file].parents) {
+            for (var xml_child in munge.files[file].parents[selector]) {
+                var val = munge.files[file].parents[selector][xml_child];
+                // if node not in base, add it to diff and base
+                // else increment it's value in base without adding to diff
+                var newlyAdded = exports.deep_add(base, [file, selector, val]);
+                if (newlyAdded) {
+                    exports.deep_add(diff, file, selector, val);
+                }
+            }
+        }
+    }
+    return diff;
+};
+
+// Update the base munge object as
+// base[file][selector][child] -= munge[file][selector][child]
+// nodes that reached zero value are removed from base and added to the returned munge
+// object.
+exports.decrement_munge = function decrement_munge(base, munge) {
+    var zeroed = { files: {} };
+
+    for (var file in munge.files) {
+        for (var selector in munge.files[file].parents) {
+            for (var xml_child in munge.files[file].parents[selector]) {
+                var val = munge.files[file].parents[selector][xml_child];
+                // if node not in base, add it to diff and base
+                // else increment it's value in base without adding to diff
+                var removed = exports.deep_remove(base, [file, selector, val]);
+                if (removed) {
+                    exports.deep_add(zeroed, file, selector, val);
+                }
+            }
+        }
+    }
+    return zeroed;
+};
+
+// For better readability where used
+exports.clone_munge = function clone_munge(munge) {
+    return exports.increment_munge({}, munge);
+};

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/CordovaError.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/CordovaError.js b/cordova-common/src/CordovaError.js
new file mode 100644
index 0000000..d9989c4
--- /dev/null
+++ b/cordova-common/src/CordovaError.js
@@ -0,0 +1,32 @@
+/**
+    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.
+*/
+
+/* jshint proto:true */
+
+// A derived exception class. See usage example in cli.js
+// Based on:
+// stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/8460753#8460753
+function CordovaError(message) {
+    Error.captureStackTrace(this, this.constructor);
+    this.name = this.constructor.name;
+    this.message = message;
+}
+CordovaError.prototype.__proto__ = Error.prototype;
+
+module.exports = CordovaError;

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/PlatformJson.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/PlatformJson.js b/cordova-common/src/PlatformJson.js
new file mode 100644
index 0000000..793e976
--- /dev/null
+++ b/cordova-common/src/PlatformJson.js
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ *
+*/
+/* jshint sub:true */
+
+var fs = require('fs');
+var path = require('path');
+var shelljs = require('shelljs');
+var mungeutil = require('./ConfigChanges/munge-util');
+var pluginMappernto = require('cordova-registry-mapper').newToOld;
+var pluginMapperotn = require('cordova-registry-mapper').oldToNew;
+
+function PlatformJson(filePath, platform, root) {
+    this.filePath = filePath;
+    this.platform = platform;
+    this.root = fix_munge(root || {});
+}
+
+PlatformJson.load = function(plugins_dir, platform) {
+    var filePath = path.join(plugins_dir, platform + '.json');
+    var root = null;
+    if (fs.existsSync(filePath)) {
+        root = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
+    }
+    return new PlatformJson(filePath, platform, root);
+};
+
+PlatformJson.prototype.save = function() {
+    shelljs.mkdir('-p', path.dirname(this.filePath));
+    fs.writeFileSync(this.filePath, JSON.stringify(this.root, null, 4), 'utf-8');
+};
+
+/**
+ * Indicates whether the specified plugin is installed as a top-level (not as
+ *  dependency to others)
+ * @method function
+ * @param  {String} pluginId A plugin id to check for.
+ * @return {Boolean} true if plugin installed as top-level, otherwise false.
+ */
+PlatformJson.prototype.isPluginTopLevel = function(pluginId) {
+    var installedPlugins = this.root.installed_plugins;
+    return installedPlugins[pluginId] ||
+        installedPlugins[pluginMappernto[pluginId]] ||
+        installedPlugins[pluginMapperotn[pluginId]];
+};
+
+/**
+ * Indicates whether the specified plugin is installed as a dependency to other
+ *  plugin.
+ * @method function
+ * @param  {String} pluginId A plugin id to check for.
+ * @return {Boolean} true if plugin installed as a dependency, otherwise false.
+ */
+PlatformJson.prototype.isPluginDependent = function(pluginId) {
+    var dependentPlugins = this.root.dependent_plugins;
+    return dependentPlugins[pluginId] ||
+        dependentPlugins[pluginMappernto[pluginId]] ||
+        dependentPlugins[pluginMapperotn[pluginId]];
+};
+
+/**
+ * Indicates whether plugin is installed either as top-level or as dependency.
+ * @method function
+ * @param  {String} pluginId A plugin id to check for.
+ * @return {Boolean} true if plugin installed, otherwise false.
+ */
+PlatformJson.prototype.isPluginInstalled = function(pluginId) {
+    return this.isPluginTopLevel(pluginId) ||
+        this.isPluginDependent(pluginId);
+};
+
+PlatformJson.prototype.addPlugin = function(pluginId, variables, isTopLevel) {
+    var pluginsList = isTopLevel ?
+        this.root.installed_plugins :
+        this.root.dependent_plugins;
+
+    pluginsList[pluginId] = variables;
+
+    return this;
+};
+
+PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) {
+    var pluginsList = isTopLevel ?
+        this.root.installed_plugins :
+        this.root.dependent_plugins;
+
+    delete pluginsList[pluginId];
+
+    return this;
+};
+
+PlatformJson.prototype.addInstalledPluginToPrepareQueue = function(pluginDirName, vars, is_top_level) {
+    this.root.prepare_queue.installed.push({'plugin':pluginDirName, 'vars':vars, 'topLevel':is_top_level});
+};
+
+PlatformJson.prototype.addUninstalledPluginToPrepareQueue = function(pluginId, is_top_level) {
+    this.root.prepare_queue.uninstalled.push({'plugin':pluginId, 'id':pluginId, 'topLevel':is_top_level});
+};
+
+/**
+ * Moves plugin, specified by id to top-level plugins. If plugin is top-level
+ *  already, then does nothing.
+ * @method function
+ * @param  {String} pluginId A plugin id to make top-level.
+ * @return {PlatformJson} PlatformJson instance.
+ */
+PlatformJson.prototype.makeTopLevel = function(pluginId) {
+    var plugin = this.root.dependent_plugins[pluginId];
+    if (plugin) {
+        delete this.root.dependent_plugins[pluginId];
+        this.root.installed_plugins[pluginId] = plugin;
+    }
+    return this;
+};
+
+// convert a munge from the old format ([file][parent][xml] = count) to the current one
+function fix_munge(root) {
+    root.prepare_queue = root.prepare_queue || {installed:[], uninstalled:[]};
+    root.config_munge = root.config_munge || {files: {}};
+    root.installed_plugins = root.installed_plugins || {};
+    root.dependent_plugins = root.dependent_plugins || {};
+
+    var munge = root.config_munge;
+    if (!munge.files) {
+        var new_munge = { files: {} };
+        for (var file in munge) {
+            for (var selector in munge[file]) {
+                for (var xml_child in munge[file][selector]) {
+                    var val = parseInt(munge[file][selector][xml_child]);
+                    for (var i = 0; i < val; i++) {
+                        mungeutil.deep_add(new_munge, [file, selector, { xml: xml_child, count: val }]);
+                    }
+                }
+            }
+        }
+        root.config_munge = new_munge;
+    }
+
+    return root;
+}
+
+module.exports = PlatformJson;
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/PluginInfo/PluginInfo.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/PluginInfo/PluginInfo.js b/cordova-common/src/PluginInfo/PluginInfo.js
new file mode 100644
index 0000000..10cfdf0
--- /dev/null
+++ b/cordova-common/src/PluginInfo/PluginInfo.js
@@ -0,0 +1,416 @@
+/**
+    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.
+*/
+
+/* jshint sub:true, laxcomma:true, laxbreak:true */
+
+/*
+A class for holidng the information currently stored in plugin.xml
+It should also be able to answer questions like whether the plugin
+is compatible with a given engine version.
+
+TODO (kamrik): refactor this to not use sync functions and return promises.
+*/
+
+
+var path = require('path')
+  , fs = require('fs')
+  , xml_helpers = require('../util/xml-helpers')
+  , CordovaError = require('../CordovaError')
+  ;
+
+function PluginInfo(dirname) {
+    var self = this;
+
+    // METHODS
+    // Defined inside the constructor to avoid the "this" binding problems.
+
+    // <preference> tag
+    // Example: <preference name="API_KEY" />
+    // Used to require a variable to be specified via --variable when installing the plugin.
+    self.getPreferences = getPreferences;
+    function getPreferences(platform) {
+        var arprefs = _getTags(self._et, 'preference', platform, _parsePreference);
+
+        var prefs= {};
+        for(var i in arprefs)
+        {
+            var pref=arprefs[i];
+            prefs[pref.preference]=pref.default;
+        }
+        // returns { key : default | null}
+        return prefs;
+    }
+
+    function _parsePreference(prefTag) {
+        var name = prefTag.attrib.name.toUpperCase();
+        var def = prefTag.attrib.default || null;
+        return {preference: name, default: def};
+    }
+
+    // <asset>
+    self.getAssets = getAssets;
+    function getAssets(platform) {
+        var assets = _getTags(self._et, 'asset', platform, _parseAsset);
+        return assets;
+    }
+
+    function _parseAsset(tag) {
+        var src = tag.attrib.src;
+        var target = tag.attrib.target;
+
+        if ( !src || !target) {
+            var msg =
+                'Malformed <asset> tag. Both "src" and "target" attributes'
+                + 'must be specified in\n'
+                + self.filepath
+                ;
+            throw new Error(msg);
+        }
+
+        var asset = {
+            itemType: 'asset',
+            src: src,
+            target: target
+        };
+        return asset;
+    }
+
+
+    // <dependency>
+    // Example:
+    // <dependency id="com.plugin.id"
+    //     url="https://github.com/myuser/someplugin"
+    //     commit="428931ada3891801"
+    //     subdir="some/path/here" />
+    self.getDependencies = getDependencies;
+    function getDependencies(platform) {
+        var deps = _getTags(
+                self._et,
+                'dependency',
+                platform,
+                _parseDependency
+        );
+        return deps;
+    }
+
+    function _parseDependency(tag) {
+        var dep =
+            { id : tag.attrib.id
+            , url : tag.attrib.url || ''
+            , subdir : tag.attrib.subdir || ''
+            , commit : tag.attrib.commit
+            };
+
+        dep.git_ref = dep.commit;
+
+        if ( !dep.id ) {
+            var msg =
+                '<dependency> tag is missing id attribute in '
+                + self.filepath
+                ;
+            throw new CordovaError(msg);
+        }
+        return dep;
+    }
+
+
+    // <config-file> tag
+    self.getConfigFiles = getConfigFiles;
+    function getConfigFiles(platform) {
+        var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
+        return configFiles;
+    }
+
+    function _parseConfigFile(tag) {
+        var configFile =
+            { target : tag.attrib['target']
+            , parent : tag.attrib['parent']
+            , after : tag.attrib['after']
+            , xmls : tag.getchildren()
+            // To support demuxing via versions
+            , versions : tag.attrib['versions']
+            , deviceTarget: tag.attrib['device-target']
+            };
+        return configFile;
+    }
+
+    // <info> tags, both global and within a <platform>
+    // TODO (kamrik): Do we ever use <info> under <platform>? Example wanted.
+    self.getInfo = getInfo;
+    function getInfo(platform) {
+        var infos = _getTags(
+                self._et,
+                'info',
+                platform,
+                function(elem) { return elem.text; }
+        );
+        // Filter out any undefined or empty strings.
+        infos = infos.filter(Boolean);
+        return infos;
+    }
+
+    // <source-file>
+    // Examples:
+    // <source-file src="src/ios/someLib.a" framework="true" />
+    // <source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
+    self.getSourceFiles = getSourceFiles;
+    function getSourceFiles(platform) {
+        var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
+        return sourceFiles;
+    }
+
+    function _parseSourceFile(tag) {
+        return {
+            itemType: 'source-file',
+            src: tag.attrib.src,
+            framework: isStrTrue(tag.attrib.framework),
+            weak: isStrTrue(tag.attrib.weak),
+            compilerFlags: tag.attrib['compiler-flags'],
+            targetDir: tag.attrib['target-dir']
+        };
+    }
+
+    // <header-file>
+    // Example:
+    // <header-file src="CDVFoo.h" />
+    self.getHeaderFiles = getHeaderFiles;
+    function getHeaderFiles(platform) {
+        var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, function(tag) {
+            return {
+                itemType: 'header-file',
+                src: tag.attrib.src,
+                targetDir: tag.attrib['target-dir']
+            };
+        });
+        return headerFiles;
+    }
+
+    // <resource-file>
+    // Example:
+    // <resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" device-target="win" arch="x86" versions="&gt;=8.1" />
+    self.getResourceFiles = getResourceFiles;
+    function getResourceFiles(platform) {
+        var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, function(tag) {
+            return {
+                itemType: 'resource-file',
+                src: tag.attrib.src,
+                target: tag.attrib.target,
+                versions: tag.attrib.versions,
+                deviceTarget: tag.attrib['device-target'],
+                arch: tag.attrib.arch
+            };
+        });
+        return resourceFiles;
+    }
+
+    // <lib-file>
+    // Example:
+    // <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />
+    self.getLibFiles = getLibFiles;
+    function getLibFiles(platform) {
+        var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, function(tag) {
+            return {
+                itemType: 'lib-file',
+                src: tag.attrib.src,
+                arch: tag.attrib.arch,
+                Include: tag.attrib.Include,
+                versions: tag.attrib.versions,
+                deviceTarget: tag.attrib['device-target'] || tag.attrib.target
+            };
+        });
+        return libFiles;
+    }
+
+    // <hook>
+    // Example:
+    // <hook type="before_build" src="scripts/beforeBuild.js" />
+    self.getHookScripts = getHookScripts;
+    function getHookScripts(hook, platforms) {
+        var scriptElements =  self._et.findall('./hook');
+
+        if(platforms) {
+            platforms.forEach(function (platform) {
+                scriptElements = scriptElements.concat(self._et.findall('./platform[@name="' + platform + '"]/hook'));
+            });
+        }
+
+        function filterScriptByHookType(el) {
+            return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
+        }
+
+        return scriptElements.filter(filterScriptByHookType);
+    }
+
+    self.getJsModules = getJsModules;
+    function getJsModules(platform) {
+        var modules = _getTags(self._et, 'js-module', platform, _parseJsModule);
+        return modules;
+    }
+
+    function _parseJsModule(tag) {
+        var ret = {
+            itemType: 'js-module',
+            name: tag.attrib.name,
+            src: tag.attrib.src,
+            clobbers: tag.findall('clobbers').map(function(tag) { return { target: tag.attrib.target }; }),
+            merges: tag.findall('merges').map(function(tag) { return { target: tag.attrib.target }; }),
+            runs: tag.findall('runs').length > 0
+        };
+
+        return ret;
+    }
+
+    self.getEngines = function() {
+        return self._et.findall('engines/engine').map(function(n) {
+            return {
+                name: n.attrib.name,
+                version: n.attrib.version,
+                platform: n.attrib.platform,
+                scriptSrc: n.attrib.scriptSrc
+            };
+        });
+    };
+
+    self.getPlatforms = function() {
+        return self._et.findall('platform').map(function(n) {
+            return { name: n.attrib.name };
+        });
+    };
+
+    self.getPlatformsArray = function() {
+        return self._et.findall('platform').map(function(n) {
+            return n.attrib.name;
+        });
+    };
+    self.getFrameworks = function(platform) {
+        return _getTags(self._et, 'framework', platform, function(el) {
+            var ret = {
+                itemType: 'framework',
+                type: el.attrib.type,
+                parent: el.attrib.parent,
+                custom: isStrTrue(el.attrib.custom),
+                src: el.attrib.src,
+                weak: isStrTrue(el.attrib.weak),
+                versions: el.attrib.versions,
+                targetDir: el.attrib['target-dir'],
+                deviceTarget: el.attrib['device-target'] || el.attrib.target,
+                arch: el.attrib.arch
+            };
+            return ret;
+        });
+    };
+
+    self.getFilesAndFrameworks = getFilesAndFrameworks;
+    function getFilesAndFrameworks(platform) {
+        // Please avoid changing the order of the calls below, files will be
+        // installed in this order.
+        var items = [].concat(
+            self.getSourceFiles(platform),
+            self.getHeaderFiles(platform),
+            self.getResourceFiles(platform),
+            self.getFrameworks(platform),
+            self.getLibFiles(platform)
+        );
+        return items;
+    }
+    ///// End of PluginInfo methods /////
+
+
+    ///// PluginInfo Constructor logic  /////
+    self.filepath = path.join(dirname, 'plugin.xml');
+    if (!fs.existsSync(self.filepath)) {
+        throw new CordovaError('Cannot find plugin.xml for plugin \'' + path.basename(dirname) + '\'. Please try adding it again.');
+    }
+
+    self.dir = dirname;
+    var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
+    var pelem = et.getroot();
+    self.id = pelem.attrib.id;
+    self.version = pelem.attrib.version;
+
+    // Optional fields
+    self.name = pelem.findtext('name');
+    self.description = pelem.findtext('description');
+    self.license = pelem.findtext('license');
+    self.repo = pelem.findtext('repo');
+    self.issue = pelem.findtext('issue');
+    self.keywords = pelem.findtext('keywords');
+    self.info = pelem.findtext('info');
+    if (self.keywords) {
+        self.keywords = self.keywords.split(',').map( function(s) { return s.trim(); } );
+    }
+    self.getKeywordsAndPlatforms = function () {
+        var ret = self.keywords || [];
+        return ret.concat('ecosystem:cordova').concat(addCordova(self.getPlatformsArray()));
+    };
+}  // End of PluginInfo constructor.
+
+// Helper function used to prefix every element of an array with cordova-
+// Useful when we want to modify platforms to be cordova-platform
+function addCordova(someArray) {
+    var newArray = someArray.map(function(element) {
+        return 'cordova-' + element;
+    });
+    return newArray;
+}
+
+// Helper function used by most of the getSomething methods of PluginInfo.
+// Get all elements of a given name. Both in root and in platform sections
+// for the given platform. If transform is given and is a function, it is
+// applied to each element.
+function _getTags(pelem, tag, platform, transform) {
+    var platformTag = pelem.find('./platform[@name="' + platform + '"]');
+    if (platform == 'windows' && !platformTag) {
+        platformTag = pelem.find('platform[@name="' + 'windows8' + '"]');
+    }
+    var tagsInRoot = pelem.findall(tag);
+    tagsInRoot = tagsInRoot || [];
+    var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
+    var tags = tagsInRoot.concat(tagsInPlatform);
+    if ( typeof transform === 'function' ) {
+        tags = tags.map(transform);
+    }
+    return tags;
+}
+
+// Same as _getTags() but only looks inside a platfrom section.
+function _getTagsInPlatform(pelem, tag, platform, transform) {
+    var platformTag = pelem.find('./platform[@name="' + platform + '"]');
+    if (platform == 'windows' && !platformTag) {
+        platformTag = pelem.find('platform[@name="' + 'windows8' + '"]');
+    }
+    var tags = platformTag ? platformTag.findall(tag) : [];
+    if ( typeof transform === 'function' ) {
+        tags = tags.map(transform);
+    }
+    return tags;
+}
+
+// Check if x is a string 'true'.
+function isStrTrue(x) {
+    return String(x).toLowerCase() == 'true';
+}
+
+module.exports = PluginInfo;
+// Backwards compat:
+PluginInfo.PluginInfo = PluginInfo;
+PluginInfo.loadPluginsDir = function(dir) {
+    var PluginInfoProvider = require('./PluginInfoProvider');
+    return new PluginInfoProvider().getAllWithinSearchPath(dir);
+};

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/28ce0d1d/cordova-common/src/PluginInfo/PluginInfoProvider.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/PluginInfo/PluginInfoProvider.js b/cordova-common/src/PluginInfo/PluginInfoProvider.js
new file mode 100644
index 0000000..6240119
--- /dev/null
+++ b/cordova-common/src/PluginInfo/PluginInfoProvider.js
@@ -0,0 +1,82 @@
+/**
+    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.
+*/
+
+/* jshint sub:true, laxcomma:true, laxbreak:true */
+
+var fs = require('fs');
+var path = require('path');
+var PluginInfo = require('./PluginInfo');
+var events = require('../events');
+
+function PluginInfoProvider() {
+    this._cache = {};
+    this._getAllCache = {};
+}
+
+PluginInfoProvider.prototype.get = function(dirName) {
+    var absPath = path.resolve(dirName);
+    if (!this._cache[absPath]) {
+        this._cache[absPath] = new PluginInfo(dirName);
+    }
+    return this._cache[absPath];
+};
+
+// Normally you don't need to put() entries, but it's used
+// when copying plugins, and in unit tests.
+PluginInfoProvider.prototype.put = function(pluginInfo) {
+    var absPath = path.resolve(pluginInfo.dir);
+    this._cache[absPath] = pluginInfo;
+};
+
+// Used for plugin search path processing.
+// Given a dir containing multiple plugins, create a PluginInfo object for
+// each of them and return as array.
+// Should load them all in parallel and return a promise, but not yet.
+PluginInfoProvider.prototype.getAllWithinSearchPath = function(dirName) {
+    var absPath = path.resolve(dirName);
+    if (!this._getAllCache[absPath]) {
+        this._getAllCache[absPath] = getAllHelper(absPath, this);
+    }
+    return this._getAllCache[absPath];
+};
+
+function getAllHelper(absPath, provider) {
+    if (!fs.existsSync(absPath)){
+        return [];
+    }
+    // If dir itself is a plugin, return it in an array with one element.
+    if (fs.existsSync(path.join(absPath, 'plugin.xml'))) {
+        return [provider.get(absPath)];
+    }
+    var subdirs = fs.readdirSync(absPath);
+    var plugins = [];
+    subdirs.forEach(function(subdir) {
+        var d = path.join(absPath, subdir);
+        if (fs.existsSync(path.join(d, 'plugin.xml'))) {
+            try {
+                plugins.push(provider.get(d));
+            } catch (e) {
+                events.emit('warn', 'Error parsing ' + path.join(d, 'plugin.xml.\n' + e.stack));
+            }
+        }
+    });
+    return plugins;
+}
+
+module.exports = PluginInfoProvider;


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


[07/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.multiple-children/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.multiple-children/plugin.xml b/cordova-common/spec/fixtures/plugins/org.test.multiple-children/plugin.xml
new file mode 100644
index 0000000..08576c5
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.multiple-children/plugin.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.org.test.multiple-children"
+    version="3.0.0">
+
+    <name>Pushwoosh</name>
+
+    <!-- android -->
+    <platform name="android">
+		<config-file target="AndroidManifest.xml" parent="/manifest">
+			<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+			
+			<!--library-->
+			<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+			
+			<!-- GCM connects to Google Services. -->
+			<uses-permission android:name="android.permission.INTERNET"/>
+			
+			<!-- GCM requires a Google account. -->
+			<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
+			
+			<!-- Keeps the processor from sleeping when a message is received. -->
+			<uses-permission android:name="android.permission.WAKE_LOCK"/>
+			
+			<!--
+			 Creates a custom permission so only this app can receive its messages.
+			 
+			 NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
+			 where PACKAGE is the application's package name.
+			 -->
+			<permission
+			android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"
+			android:protectionLevel="signature"/>
+			<uses-permission
+			android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"/>
+			
+			<!-- This app has permission to register and receive data message. -->
+			<uses-permission
+			android:name="com.google.android.c2dm.permission.RECEIVE"/>
+		</config-file>
+		
+		<config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
+			<intent-filter>
+				<action android:name="$PACKAGE_NAME.MESSAGE"/>
+				<category android:name="android.intent.category.DEFAULT"/>
+			</intent-filter>
+		</config-file>
+
+		<config-file target="AndroidManifest.xml" parent="/manifest/application">
+			<activity android:name="com.arellomobile.android.push.PushWebview"/>
+			
+			<activity android:name="com.arellomobile.android.push.MessageActivity"/>
+			
+			<activity android:name="com.arellomobile.android.push.PushHandlerActivity"/>
+			
+			<!--
+			 BroadcastReceiver that will receive intents from GCM
+			 services and handle them to the custom IntentService.
+			 
+			 The com.google.android.c2dm.permission.SEND permission is necessary
+			 so only GCM services can send data messages for the app.
+			 -->
+			<receiver
+				android:name="com.google.android.gcm.GCMBroadcastReceiver"
+				android:permission="com.google.android.c2dm.permission.SEND">
+				<intent-filter>
+					<!-- Receives the actual messages. -->
+					<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
+					<!-- Receives the registration id. -->
+					<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
+					<category android:name="$PACKAGE_NAME"/>
+				</intent-filter>
+			</receiver>
+			
+			<!--
+			 Application-specific subclass of PushGCMIntentService that will
+			 handle received messages.
+			 -->
+			<service android:name="com.arellomobile.android.push.PushGCMIntentService"/>        					
+			
+		</config-file>
+		
+		<config-file target="res/xml/plugins.xml" parent="/plugins">
+            <plugin name="PushNotification"
+			value="com.pushwoosh.test.plugin.pushnotifications.PushNotifications" onload="true"/>
+        </config-file>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/plugin.xml b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/plugin.xml
new file mode 100644
index 0000000..fd65360
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/plugin.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.plugins.childbrowser"
+    version="0.6.0">
+
+    <name>Child Browser</name>
+
+    <asset src="www/childbrowser" target="childbrowser" />
+    <asset src="www/childbrowser_file.html" target="childbrowser_file.html" />
+
+    <js-module src="www/childbrowser.js" name="org.test.plugins.childbrowser">
+        <clobbers target="childbrowser" />
+    </js-module>
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+        <access origin="s3.amazonaws.com" />
+    </config-file>
+
+    <info>No matter what platform you are installing to, this notice is very important.</info>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity android:name="org.test.plugins.childBrowser.org.test.plugins.childbrowser"
+                      android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
+
+        <!-- CDV < 2.0 -->
+        <config-file target="res/xml/plugins.xml" parent="/plugins">
+            <plugin name="org.test.plugins.childbrowser"
+                value="org.test.plugins.childBrowser.org.test.plugins.childbrowser"/>
+        </config-file>
+
+        <!-- CDV 2.0+ (for now) -->
+        <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+            <plugin name="org.test.plugins.childbrowser"
+                value="org.test.plugins.childBrowser.org.test.plugins.childbrowser"/>
+        </config-file>
+
+        <source-file src="src/android/org.test.plugins.childbrowser.java"
+                target-dir="src/com/phonegap/plugins/childBrowser" />
+        <info>Please make sure you read this because it is very important to complete the installation of your plugin.</info>
+    </platform>
+
+    <!-- ios -->
+    <platform name="ios">
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="org.test.plugins.childbrowser"
+                value="ChildBrowserCommand" />
+        </config-file>
+
+        <resource-file src="src/ios/org.test.plugins.childbrowser.bundle" />
+        <resource-file src="src/ios/ChildBrowserViewController.xib" />
+
+        <config-file target="*-Info.plist" parent="AppId">
+            <string>$APP_ID</string>
+        </config-file>
+
+        <config-file target="*-Info.plist" parent="CFBundleURLTypes">
+            <array>
+              <dict>
+                <key>PackageName</key>
+                <string>$PACKAGE_NAME</string>
+              </dict>
+            </array>
+        </config-file>
+
+        <header-file src="src/ios/ChildBrowserCommand.h" />
+        <header-file src="src/ios/ChildBrowserViewController.h" />
+        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir"/>
+
+        <source-file src="src/ios/ChildBrowserCommand.m" />
+        <source-file src="src/ios/ChildBrowserViewController.m" />
+        <source-file src="src/ios/preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
+        <header-file src="src/ios/TargetDirTest.m" target-dir="targetDir"/>
+
+        <!-- framework for testing (not actual dependency of org.test.plugins.childbrowser -->
+        <framework src="libsqlite3.dylib" />
+        <framework src="social.framework" weak="true" />
+        <framework src="music.framework" weak="rabbit" />
+        <framework src="Custom.framework" custom="true" />
+    </platform>
+
+    <!-- wp8 -->
+    <platform name="wp8">
+        <resource-file src="src\wp7\Images\appbar.back.rest.png" />
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="org.test.plugins.childbrowser"
+                value="org.test.plugins.childbrowser"/>
+        </config-file>
+
+        <source-file src="src\wp7\ChildBrowserCommand.cs"
+                     target-dir="Plugins\" />
+
+        <!-- modify the project file to include the added files -->
+        <config-file target=".csproj" parent=".">
+        </config-file>
+
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/android/ChildBrowser.java
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/android/ChildBrowser.java b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/android/ChildBrowser.java
new file mode 100644
index 0000000..711b8c8
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/android/ChildBrowser.java
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/android/org.test.plugins.childbrowser.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left.png
new file mode 100644
index 0000000..9328e23
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/arrow_left.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left@2x.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left@2x.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left@2x.png
new file mode 100644
index 0000000..f32681d
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_left@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/arrow_left@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right.png
new file mode 100644
index 0000000..17a8c52
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/arrow_right.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right@2x.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right@2x.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right@2x.png
new file mode 100644
index 0000000..1d5606c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/arrow_right@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/arrow_right@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh.png
new file mode 100644
index 0000000..1ee2969
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/but_refresh.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh@2x.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh@2x.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh@2x.png
new file mode 100644
index 0000000..8a9d962
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/but_refresh@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/but_refresh@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass.png
new file mode 100644
index 0000000..e554b3c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/compass.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass@2x.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass@2x.png b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass@2x.png
new file mode 100644
index 0000000..6fdb07d
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowser.bundle/compass@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/org.test.plugins.childbrowser.bundle/compass@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.h
new file mode 100644
index 0000000..67b9b25
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.h
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.m
new file mode 100644
index 0000000..78ae968
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.m
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/ChildBrowserCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.h
new file mode 100644
index 0000000..8727cdb
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.h
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.m
new file mode 100644
index 0000000..49afd97
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.m
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.xib
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.xib b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.xib
new file mode 100644
index 0000000..50d78c3
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.xib
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/ChildBrowserViewController.xib

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.h
new file mode 100644
index 0000000..c68dfb0
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.h
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/TargetDirTest.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.m
new file mode 100644
index 0000000..f55f308
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/TargetDirTest.m
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/TargetDirTest.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.h
new file mode 100644
index 0000000..31f2b1b
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.h
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.m
new file mode 100644
index 0000000..9581443
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.m
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/src/ios/preserveDirs/PreserveDirsTest.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser.js b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser.js
new file mode 100644
index 0000000..9e15656
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser.js
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/www/childbrowser.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser/image.jpg
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser/image.jpg b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser/image.jpg
new file mode 100644
index 0000000..eff6be3
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser/image.jpg
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/www/childbrowser/image.jpg

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser_file.html
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser_file.html b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser_file.html
new file mode 100644
index 0000000..f1027f8
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.childbrowser/www/childbrowser_file.html
@@ -0,0 +1 @@
+./org.test.plugins.childbrowser/www/childbrowser_file.html

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/android-resource.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/android-resource.xml b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/android-resource.xml
new file mode 100644
index 0000000..9046e6e
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/android-resource.xml
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/android-resource.xml

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/extra.gradle
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/extra.gradle b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/extra.gradle
new file mode 100644
index 0000000..5b828a9
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/extra.gradle
@@ -0,0 +1 @@
+extra.gradle

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/AndroidManifest.xml b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/AndroidManifest.xml
new file mode 100644
index 0000000..3c9499c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  android:versionCode="1" package="com.test.somelib">
+    <uses-sdk android:minSdkVersion="9"/>
+    <application/>
+</manifest>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/libFile
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/libFile b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/libFile
new file mode 100644
index 0000000..c79df8e
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/libFile
@@ -0,0 +1 @@
+libFile contents

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/project.properties
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/project.properties b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/project.properties
new file mode 100644
index 0000000..c4a5b63
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin-lib/project.properties
@@ -0,0 +1 @@
+target=android-11

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin.xml b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin.xml
new file mode 100644
index 0000000..02bb445
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/plugin.xml
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.plugins.dummyplugin"
+    version="0.6.0">
+
+    <!-- new requirement: NO SPACES -->
+    <name>dummyplugin</name>
+    <!-- These are going to be required by plugman-registry -->
+    <description>my description</description>
+    <author>Jackson Badman</author>
+    <keywords>dummy,plugin</keywords>
+    <license>BSD</license>
+    <!-- end plugman-registry requirements -->
+
+    <asset src="www/dummyplugin.js" target="dummyplugin.js" />
+    <asset src="www/dummyplugin" target="dummyplugin" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+        <access origin="s3.amazonaws.com" />
+    </config-file>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity android:name="DummyPlugin.org.test.plugins.dummyplugin"
+                      android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
+
+        <framework src="plugin-lib" custom="true" />
+        <framework src="extras/android/support/v7/appcompat" />
+        <framework src="extra.gradle" type="gradleReference" />
+        <resource-file src="android-resource.xml" target="res/xml/dummy.xml" />
+
+        <!-- CDV < 2.0 -->
+        <config-file target="res/xml/plugins.xml" parent="/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPlugin.org.test.plugins.dummyplugin"/>
+        </config-file>
+
+        <!-- CDV 2.0+ (for now) -->
+        <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPlugin.org.test.plugins.dummyplugin"/>
+        </config-file>
+
+        <source-file src="src/android/DummyPlugin.java"
+                target-dir="src/com/phonegap/plugins/dummyplugin" />
+        <lib-file src="src/android/TestLib.jar" />
+    </platform>
+
+    <!-- amazon fireos -->
+    <platform name="amazon-fireos">
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity android:name="DummyPlugin.org.test.plugins.dummyplugin"
+                      android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
+
+        <!-- CDV < 2.0 -->
+        <config-file target="res/xml/plugins.xml" parent="/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPlugin.org.test.plugins.dummyplugin"/>
+        </config-file>
+
+        <!-- CDV 2.0+ (for now) -->
+        <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPlugin.org.test.plugins.dummyplugin"/>
+        </config-file>
+
+        <source-file src="src/android/DummyPlugin.java"
+                target-dir="src/com/phonegap/plugins/dummyplugin" />
+        <lib-file src="src/android/TestLib.jar" />
+    </platform>
+
+    <!-- blackberry10 -->
+    <platform name="blackberry10">
+        <config-file target="www/config.xml" parent="/widget">
+            <feature id="dummyPlugin" required="true" version="1.0.0.0"/>
+        </config-file>
+
+        <source-file src="src/blackberry10/index.js"/>
+        <js-module src="www/dummyplugin.js" name="Dummy">
+            <clobbers target="dummy" />
+        </js-module>
+    </platform>
+
+
+    <!-- ios -->
+    <platform name="ios">
+        <!-- CDV 2.5+ -->
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPluginCommand"/>
+        </config-file>
+
+        <resource-file src="src/ios/DummyPlugin.bundle" />
+
+        <header-file src="src/ios/DummyPluginCommand.h" />
+        <source-file src="src/ios/DummyPluginCommand.m"/>
+
+        <source-file src="src/ios/SourceWithFramework.m" framework="true" />
+
+        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir" />
+        <source-file src="src/ios/TargetDirTest.m" target-dir="targetDir" />
+
+        <!-- framework for testing (not actual dependency of org.test.plugins.dummyplugin -->
+        <framework src="src/ios/libsqlite3.dylib" />
+        <framework src="src/ios/libsqlite3.dylib" weak="true" />
+        <framework src="src/ios/Custom.framework" custom="true" />
+    </platform>
+
+    <!-- wp8 -->
+    <platform name="wp8">
+        <config-file target="config.xml" parent="/*">
+            <feature id="dummyPlugin" required="true" version="1.0.0.0"/>
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App" after="Tokens">
+            <Extensions />
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Extensions" after="Extension">
+            <Extension ExtensionName="DummyExtension1" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}" TaskID="_default" ExtraFile="Extensions\\Extras.xml" />
+            <Extension ExtensionName="DummyExtension2" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}" TaskID="_default" ExtraFile="Extensions\\Extras.xml" />
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Extensions" after="FileTypeAssociation;Extension">
+            <FileTypeAssociation TaskID="_default" Name="DummyFileType1" NavUriFragment="fileToken=%s">
+                <SupportedFileTypes>
+                    <FileType ContentType="application/dummy1">.dummy1</FileType>
+                </SupportedFileTypes>
+            </FileTypeAssociation>
+            <FileTypeAssociation TaskID="_default" Name="DummyFileType2" NavUriFragment="fileToken=%s">
+                <SupportedFileTypes>
+                    <FileType ContentType="application/dummy2">.dummy2</FileType>
+                </SupportedFileTypes>
+            </FileTypeAssociation>
+        </config-file>
+
+        <source-file src="src/wp8/DummyPlugin.cs"/>
+        <js-module src="www/dummyplugin.js" name="Dummy">
+            <clobbers target="dummy" />
+        </js-module>
+    </platform>
+
+    <!-- tizen -->
+    <platform name="tizen">
+        <source-file src="src/tizen/dummer.js"/>
+    </platform>
+
+    <!-- windows -->
+    <platform name="windows">
+        <config-file target="config.xml" parent="/*">
+            <feature id="dummyPlugin" required="true" version="1.0.0.0"/>
+        </config-file>
+
+        <source-file src="src/windows/dummer.js"/>
+
+        <lib-file src="TestSDK1, Version=1.0" arch="x86"/>
+        <lib-file src="TestSDK2, Version=1.0" versions=">=8.1"/>
+        <lib-file src="TestSDK3, Version=1.0" device-target="phone"/>
+        <lib-file src="TestSDK4, Version=1.0" device-target="windows" versions="8.0" arch="x86"/>
+
+        <framework src="src/windows/dummy1.dll" arch="x64"/>
+        <framework src="src/windows/dummy2.dll" versions=">=8.0"/>
+        <framework src="src/windows/dummy3.dll" device-target="windows"/>
+        <framework src="src/windows/dummy4.dll" device-target="phone" versions="8.1" arch="ARM"/>
+
+        <framework src="src/windows/dummy1.vcxproj" type="projectReference" arch="x64"/>
+        <framework src="src/windows/dummy2.vcxproj" type="projectReference" versions="<8.1"/>
+        <!-- "target" attribute is an alias for "device-target" (but is deprecated) - test for it here -->
+        <framework src="src/windows/dummy3.vcxproj" type="projectReference" target="win"/>
+        <framework src="src/windows/dummy4.vcxproj" type="projectReference" device-target="all" versions="8.1" arch="x86"/>
+
+        <js-module src="www/dummyplugin.js" name="Dummy">
+            <clobbers target="dummy" />
+        </js-module>
+    </platform>
+
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/android/DummyPlugin.java
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/android/DummyPlugin.java b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/android/DummyPlugin.java
new file mode 100644
index 0000000..90e4f5a
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/android/DummyPlugin.java
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/android/DummyPlugin.java

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/blackberry10/index.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/blackberry10/index.js b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/blackberry10/index.js
new file mode 100644
index 0000000..691fd3e
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/blackberry10/index.js
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/blackberry10/index.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
new file mode 100644
index 0000000..fc09fe4
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
new file mode 100644
index 0000000..9e93c21
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
new file mode 100644
index 0000000..70cd334
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
new file mode 100644
index 0000000..2d8fb01
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
new file mode 100644
index 0000000..51cd929
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
new file mode 100644
index 0000000..de7b1d7
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
new file mode 100644
index 0000000..a83006f
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/TargetDirTest.h

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
new file mode 100644
index 0000000..95f2620
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/TargetDirTest.m

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
new file mode 100644
index 0000000..fd3be07
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/tizen/dummer.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/tizen/dummer.js b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/tizen/dummer.js
new file mode 100644
index 0000000..d3a91c2
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/tizen/dummer.js
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/tizen/dummer.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummer.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummer.js b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummer.js
new file mode 100644
index 0000000..48388bc
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummer.js
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/windows8/dummer.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.dll
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.dll b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.dll
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.vcxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.vcxproj b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.vcxproj
new file mode 100644
index 0000000..c454905
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy1.vcxproj
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup Label="Globals">
+        <ProjectGuid>{ef7dd979-6f12-4bdf-8754-9468ce799c4d}</ProjectGuid>
+        <ProjectName>dummy1</ProjectName>
+    </PropertyGroup>
+</Project>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.dll
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.dll b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.dll
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.vcxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.vcxproj b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.vcxproj
new file mode 100644
index 0000000..8edd706
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy2.vcxproj
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup Label="Globals">
+        <ProjectGuid>{6a760eea-8c27-442e-b98b-a487964ded42}</ProjectGuid>
+        <ProjectName>dummy2</ProjectName>
+    </PropertyGroup>
+</Project>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.dll
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.dll b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.dll
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.vcxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.vcxproj b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.vcxproj
new file mode 100644
index 0000000..600167c
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy3.vcxproj
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup Label="Globals">
+        <ProjectGuid>{5318c3c8-0921-4870-b4ad-8cce06c88238}</ProjectGuid>
+        <ProjectName>dummy3</ProjectName>
+    </PropertyGroup>
+</Project>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.dll
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.dll b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.dll
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.vcxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.vcxproj b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.vcxproj
new file mode 100644
index 0000000..d7acf04
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/windows/dummy4.vcxproj
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup Label="Globals">
+        <ProjectGuid>{8e430a1b-094b-4c27-8b76-fdd7021dbfe9}</ProjectGuid>
+        <ProjectName>dummy4</ProjectName>
+    </PropertyGroup>
+</Project>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp7/DummyPlugin.cs
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp7/DummyPlugin.cs b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp7/DummyPlugin.cs
new file mode 100644
index 0000000..d962cb8
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp7/DummyPlugin.cs
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/wp7/DummyPlugin.cs

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp8/DummyPlugin.cs
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp8/DummyPlugin.cs b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp8/DummyPlugin.cs
new file mode 100644
index 0000000..f691316
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/src/wp8/DummyPlugin.cs
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/wp8/DummyPlugin.cs

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin.js b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin.js
new file mode 100644
index 0000000..631d6da
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin.js
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/www/dummyplugin.js

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
new file mode 100644
index 0000000..219c78a
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/www/dummyplugin/image.jpg

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/plugins/org.test.shareddeps/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/plugins/org.test.shareddeps/plugin.xml b/cordova-common/spec/fixtures/plugins/org.test.shareddeps/plugin.xml
new file mode 100644
index 0000000..fb669c8
--- /dev/null
+++ b/cordova-common/spec/fixtures/plugins/org.test.shareddeps/plugin.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.shareddeps"
+    version="1.0.0">
+
+    <name>Sharing Dependencies with the Multi-Child Plugin, woo</name>
+
+    <!-- android -->
+    <platform name="android">
+		<config-file target="AndroidManifest.xml" parent="/manifest">
+			<uses-permission android:name="android.permission.INTERNET"/>
+		</config-file>
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android/AndroidManifest.xml b/cordova-common/spec/fixtures/projects/android/AndroidManifest.xml
new file mode 100644
index 0000000..0c52803
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android/AndroidManifest.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
+      package="com.alunny.childapp" android:versionName="1.1" android:versionCode="5">
+    <supports-screens
+    	android:largeScreens="true"
+    	android:normalScreens="true"
+    	android:smallScreens="true"
+    	android:xlargeScreens="true"
+    	android:resizeable="true"
+    	android:anyDensity="true"
+    	/>
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.RECORD_VIDEO"/>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />   
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name"
+    	android:debuggable="true">
+		<activity android:name="ChildApp" android:label="@string/app_name" 
+				  android:configChanges="orientation|keyboardHidden">
+			<intent-filter>
+				<action android:name="android.intent.action.MAIN" />
+				<category android:name="android.intent.category.LAUNCHER" />
+			</intent-filter>
+        </activity>
+        <activity android:name="com.phonegap.DroidGap" android:label="@string/app_name" 
+            	  android:configChanges="orientation|keyboardHidden">
+        	<intent-filter>
+        	</intent-filter>
+        </activity>
+    </application>
+
+	<uses-sdk android:minSdkVersion="5" />
+</manifest> 

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android/assets/www/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android/assets/www/.gitkeep b/cordova-common/spec/fixtures/projects/android/assets/www/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android/res/xml/config.xml b/cordova-common/spec/fixtures/projects/android/res/xml/config.xml
new file mode 100644
index 0000000..d37aba5
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android/res/xml/config.xml
@@ -0,0 +1,54 @@
+<?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.
+-->
+<cordova>
+    <!--
+    access elements control the Android whitelist.
+    Domains are assumed blocked unless set otherwise
+     -->
+
+    <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
+
+    <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
+    <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
+    <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
+
+    <log level="DEBUG"/>
+    <preference name="useBrowserHistory" value="false" />
+<plugins>
+    <plugin name="App" value="org.apache.cordova.App"/>
+    <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
+    <plugin name="Device" value="org.apache.cordova.Device"/>
+    <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
+    <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
+    <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
+    <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
+    <plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
+    <plugin name="File" value="org.apache.cordova.FileUtils"/>
+    <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
+    <plugin name="Notification" value="org.apache.cordova.Notification"/>
+    <plugin name="Storage" value="org.apache.cordova.Storage"/>
+    <plugin name="Temperature" value="org.apache.cordova.TempListener"/>
+    <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
+    <plugin name="Capture" value="org.apache.cordova.Capture"/>
+    <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
+    <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
+</plugins>
+</cordova>
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android/src/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android/src/.gitkeep b/cordova-common/spec/fixtures/projects/android/src/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two/AndroidManifest.xml b/cordova-common/spec/fixtures/projects/android_two/AndroidManifest.xml
new file mode 100644
index 0000000..17489ca
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android_two/AndroidManifest.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
+      package="com.alunny.childapp" android:versionName="1.1" android:versionCode="5">
+    <supports-screens
+    	android:largeScreens="true"
+    	android:normalScreens="true"
+    	android:smallScreens="true"
+    	android:xlargeScreens="true"
+    	android:resizeable="true"
+    	android:anyDensity="true"
+    	/>
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.RECORD_VIDEO"/>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />   
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name"
+    	android:debuggable="true">
+		<activity android:name="ChildApp" android:label="@string/app_name" 
+				  android:configChanges="orientation|keyboardHidden">
+			<intent-filter>
+				<action android:name="android.intent.action.MAIN" />
+				<category android:name="android.intent.category.LAUNCHER" />
+			</intent-filter>
+        </activity>
+        <activity android:name="org.test.DroidGap" android:label="@string/app_name" 
+            	  android:configChanges="orientation|keyboardHidden">
+        	<intent-filter>
+        	</intent-filter>
+        </activity>
+    </application>
+
+	<uses-sdk android:minSdkVersion="5" />
+</manifest> 

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two/assets/www/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two/assets/www/.gitkeep b/cordova-common/spec/fixtures/projects/android_two/assets/www/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two/res/xml/config.xml b/cordova-common/spec/fixtures/projects/android_two/res/xml/config.xml
new file mode 100644
index 0000000..4f087a9
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android_two/res/xml/config.xml
@@ -0,0 +1,54 @@
+<?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.
+-->
+<cordova>
+    <!--
+    access elements control the Android whitelist.
+    Domains are assumed blocked unless set otherwise
+     -->
+
+    <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
+
+    <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
+    <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
+    <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
+
+    <log level="DEBUG"/>
+    <preference name="useBrowserHistory" value="false" />
+<plugins>
+    <plugin name="App" value="org.apache.cordova.App"/>
+    <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
+    <plugin name="Device" value="org.apache.cordova.Device"/>
+    <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
+    <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
+    <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
+    <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
+    <plugin name="org.apache.cordova.core.contacts" value="org.apache.cordova.ContactManager"/>
+    <plugin name="File" value="org.apache.cordova.FileUtils"/>
+    <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
+    <plugin name="Notification" value="org.apache.cordova.Notification"/>
+    <plugin name="Storage" value="org.apache.cordova.Storage"/>
+    <plugin name="Temperature" value="org.apache.cordova.TempListener"/>
+    <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
+    <plugin name="Capture" value="org.apache.cordova.Capture"/>
+    <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
+    <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
+</plugins>
+</cordova>
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two/src/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two/src/.gitkeep b/cordova-common/spec/fixtures/projects/android_two/src/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two_no_perms/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two_no_perms/AndroidManifest.xml b/cordova-common/spec/fixtures/projects/android_two_no_perms/AndroidManifest.xml
new file mode 100644
index 0000000..f4fcb54
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android_two_no_perms/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ 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.
+
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
+      package="com.alunny.childapp" android:versionName="1.1" android:versionCode="5">
+    <supports-screens
+    	android:largeScreens="true"
+    	android:normalScreens="true"
+    	android:smallScreens="true"
+    	android:xlargeScreens="true"
+    	android:resizeable="true"
+    	android:anyDensity="true"
+    	/>
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name"
+    	android:debuggable="true">
+		<activity android:name="ChildApp" android:label="@string/app_name" 
+				  android:configChanges="orientation|keyboardHidden">
+			<intent-filter>
+				<action android:name="android.intent.action.MAIN" />
+				<category android:name="android.intent.category.LAUNCHER" />
+			</intent-filter>
+        </activity>
+        <activity android:name="org.test.DroidGap" android:label="@string/app_name" 
+            	  android:configChanges="orientation|keyboardHidden">
+        	<intent-filter>
+        	</intent-filter>
+        </activity>
+    </application>
+
+	<uses-sdk android:minSdkVersion="5" />
+</manifest> 

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two_no_perms/assets/www/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two_no_perms/assets/www/.gitkeep b/cordova-common/spec/fixtures/projects/android_two_no_perms/assets/www/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two_no_perms/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two_no_perms/res/xml/config.xml b/cordova-common/spec/fixtures/projects/android_two_no_perms/res/xml/config.xml
new file mode 100644
index 0000000..4f087a9
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/android_two_no_perms/res/xml/config.xml
@@ -0,0 +1,54 @@
+<?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.
+-->
+<cordova>
+    <!--
+    access elements control the Android whitelist.
+    Domains are assumed blocked unless set otherwise
+     -->
+
+    <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
+
+    <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
+    <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
+    <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
+
+    <log level="DEBUG"/>
+    <preference name="useBrowserHistory" value="false" />
+<plugins>
+    <plugin name="App" value="org.apache.cordova.App"/>
+    <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
+    <plugin name="Device" value="org.apache.cordova.Device"/>
+    <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
+    <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
+    <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
+    <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
+    <plugin name="org.apache.cordova.core.contacts" value="org.apache.cordova.ContactManager"/>
+    <plugin name="File" value="org.apache.cordova.FileUtils"/>
+    <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
+    <plugin name="Notification" value="org.apache.cordova.Notification"/>
+    <plugin name="Storage" value="org.apache.cordova.Storage"/>
+    <plugin name="Temperature" value="org.apache.cordova.TempListener"/>
+    <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
+    <plugin name="Capture" value="org.apache.cordova.Capture"/>
+    <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
+    <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
+</plugins>
+</cordova>
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/android_two_no_perms/src/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/android_two_no_perms/src/.gitkeep b/cordova-common/spec/fixtures/projects/android_two_no_perms/src/.gitkeep
new file mode 100644
index 0000000..e69de29


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


[10/10] cordova-lib git commit: Pick ConfigParser changes from apache@ddb027b

Posted by sg...@apache.org.
Pick ConfigParser changes from apache@ddb027b

github close #309


Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/1594c0af
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/1594c0af
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/1594c0af

Branch: refs/heads/master
Commit: 1594c0afa89c82775f0896b6ff729c0bd7f109a7
Parents: 4909fac
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Fri Sep 18 14:16:01 2015 +0300
Committer: sgrebnov <v-...@microsoft.com>
Committed: Sun Sep 20 15:17:17 2015 +0300

----------------------------------------------------------------------
 cordova-common/src/configparser/ConfigParser.js | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/1594c0af/cordova-common/src/configparser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/cordova-common/src/configparser/ConfigParser.js b/cordova-common/src/configparser/ConfigParser.js
index 5006a4d..0529651 100644
--- a/cordova-common/src/configparser/ConfigParser.js
+++ b/cordova-common/src/configparser/ConfigParser.js
@@ -122,6 +122,9 @@ ConfigParser.prototype = {
     version: function() {
         return this.doc.getroot().attrib['version'];
     },
+    windows_packageVersion: function() {
+        return this.doc.getroot().attrib('windows-packageVersion');
+    },
     android_versionCode: function() {
         return this.doc.getroot().attrib['android-versionCode'];
     },


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


[04/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/cordova-2.6.0.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/cordova-2.6.0.js b/cordova-common/spec/fixtures/projects/windows8/www/cordova-2.6.0.js
new file mode 100644
index 0000000..bb99ae6
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/cordova-2.6.0.js
@@ -0,0 +1,8075 @@
+// Platform: windows8
+
+// commit 125dca530923a44a8f44f68f5e1970cbdd4e7faf
+
+// File generated at :: Wed Apr 03 2013 13:20:16 GMT-0700 (Pacific Daylight Time)
+
+/*
+ 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() {
+
+// file: lib\scripts\require.js
+
+var require,
+    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 = {};
+
+    function build(module) {
+        var factory = module.factory;
+        module.exports = {};
+        delete module.factory;
+        factory(require, 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: lib/cordova.js
+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(){}
+    };
+}
+
+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() {
+                  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;
+
+});
+
+// file: lib\common\argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+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 jake test.
+        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: lib\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);
+    obj[key] = value;
+    // Getters can only be overridden by getters.
+    if (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: lib\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.
+ * onCordovaInfoReady*         Internal event fired when device properties are available.
+ * onCordovaConnectionReady*   Internal event fired when the connection property has been set.
+ * 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
+ * onDestroy*                  Internal event fired when app is being destroyed (User should use window.onunload event, not this one).
+ *
+ * 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 forceFunction(f) {
+    if (typeof f != 'function') throw "Function required as first argument!";
+}
+
+/**
+ * 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(f, c) {
+    // need a function to call
+    forceFunction(f);
+    if (this.state == 2) {
+        f.apply(c || this, this.fireArgs);
+        return;
+    }
+
+    var func = f,
+        guid = f.observer_guid;
+    if (typeof c == "object") { func = utils.close(c, f); }
+
+    if (!guid) {
+        // first time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    func.observer_guid = guid;
+    f.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = func;
+        this.numHandlers++;
+        if (this.numHandlers == 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function(f) {
+    // need a function to unsubscribe
+    forceFunction(f);
+
+    var guid = f.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 device properties are available
+channel.createSticky('onCordovaInfoReady');
+
+// Event to indicate that the connection property has been set.
+channel.createSticky('onCordovaConnectionReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+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');
+
+// Event to indicate a destroy lifecycle event
+channel.createSticky('onDestroy');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onCordovaConnectionReady');
+
+module.exports = channel;
+
+});
+
+// file: lib\common\commandProxy.js
+define("cordova/commandProxy", 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: lib\windows8\exec.js
+define("cordova/exec", function(require, exports, module) {
+
+var cordova = require('cordova');
+var commandProxy = require('cordova/commandProxy');
+
+/**
+ * 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
+ */
+module.exports = function(success, fail, service, action, args) {
+
+    var proxy = commandProxy.get(service,action);
+    if(proxy) {
+        var callbackId = service + cordova.callbackId++;
+        // console.log("EXEC:" + service + " : " + action);
+        if (typeof success == "function" || typeof fail == "function") {
+            cordova.callbacks[callbackId] = {success:success, fail:fail};
+        }
+        try {
+            proxy(success, fail, args);
+        }
+        catch(e) {
+            console.log("Exception calling native with command :: " + service + " :: " + action  + " ::exception=" + e);
+        }
+    }
+    else {
+        fail && fail("Missing Command Error");
+    }
+};
+
+});
+
+// file: lib\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);
+};
+
+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 symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var module = require(moduleName);
+        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.loadMatchingModules = function(matchingRegExp) {
+    for (var k in moduleMap) {
+        if (matchingRegExp.exec(k)) {
+            require(k);
+        }
+    }
+};
+
+exports.reset();
+
+
+});
+
+// file: lib\windows8\platform.js
+define("cordova/platform", function(require, exports, module) {
+
+var cordova = require('cordova'),
+    exec = require('cordova/exec'),
+    channel = cordova.require("cordova/channel");
+
+/*
+ * Define native implementations ( there is no native layer, so need to make sure the proxies are there )
+*/
+
+require('cordova/plugin/windows8/DeviceProxy');
+require('cordova/plugin/windows8/NetworkStatusProxy');
+require('cordova/plugin/windows8/AccelerometerProxy');
+require('cordova/plugin/windows8/CameraProxy');
+require('cordova/plugin/windows8/CaptureProxy');
+require('cordova/plugin/windows8/CompassProxy');
+require('cordova/plugin/windows8/ContactsProxy');
+require('cordova/plugin/windows8/FileProxy');
+
+require('cordova/plugin/windows8/FileTransferProxy');
+require('cordova/plugin/windows8/MediaProxy');
+require('cordova/plugin/windows8/NotificationProxy');
+
+
+
+module.exports = {
+    id: "windows8",
+    initialize:function() {
+        var modulemapper = require('cordova/modulemapper');
+
+        modulemapper.loadMatchingModules(/cordova.*\/symbols$/);
+        modulemapper.mapModules(window);
+
+        window.alert = window.alert || require("cordova/plugin/notification").alert;
+        window.confirm = window.confirm || require("cordova/plugin/notification").confirm;
+
+        var onWinJSReady = function () {
+            var app = WinJS.Application;
+            var checkpointHandler = function checkpointHandler() {
+                cordova.fireDocumentEvent('pause');
+            };
+
+            var resumingHandler = function resumingHandler() {
+                cordova.fireDocumentEvent('resume');
+            };
+
+            app.addEventListener("checkpoint", checkpointHandler);
+            Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", resumingHandler, false);
+            app.start();
+
+        };
+
+        if (!window.WinJS) {
+            // <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
+            var scriptElem = document.createElement("script");
+            scriptElem.src = "//Microsoft.WinJS.1.0/js/base.js";
+            scriptElem.addEventListener("load", onWinJSReady);
+            document.head.appendChild(scriptElem);
+
+            console.log("added WinJS ... ");
+        }
+        else {
+            onWinJSReady();
+        }
+    },
+    clobbers: {
+        cordova: {
+            path: 'cordova',
+            children: {
+                commandProxy: {
+                    path: 'cordova/commandProxy'
+                }
+            }
+        },
+        navigator: {
+            children: {
+                console: {
+                    path: "cordova/plugin/windows8/console"
+                }
+            }
+        }
+    }
+};
+
+});
+
+// file: lib\common\plugin\Acceleration.js
+define("cordova/plugin/Acceleration", function(require, exports, module) {
+
+var Acceleration = function(x, y, z, timestamp) {
+    this.x = x;
+    this.y = y;
+    this.z = z;
+    this.timestamp = timestamp || (new Date()).getTime();
+};
+
+module.exports = Acceleration;
+
+});
+
+// file: lib\common\plugin\Camera.js
+define("cordova/plugin/Camera", function(require, exports, module) {
+
+var argscheck = require('cordova/argscheck'),
+    exec = require('cordova/exec'),
+    Camera = require('cordova/plugin/CameraConstants'),
+    CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle');
+
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Gets a picture from source defined by "options.sourceType", and returns the
+ * image as defined by the "options.destinationType" option.
+
+ * The defaults are sourceType=CAMERA and destinationType=FILE_URI.
+ *
+ * @param {Function} successCallback
+ * @param {Function} errorCallback
+ * @param {Object} options
+ */
+cameraExport.getPicture = function(successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+                mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, "Camera", "takePicture", args);
+    return new CameraPopoverHandle();
+};
+
+cameraExport.cleanup = function(successCallback, errorCallback) {
+    exec(successCallback, errorCallback, "Camera", "cleanup", []);
+};
+
+module.exports = cameraExport;
+
+});
+
+// file: lib\common\plugin\CameraConstants.js
+define("cordova/plugin/CameraConstants", function(require, exports, module) {
+
+module.exports = {
+  DestinationType:{
+    DATA_URL: 0,         // Return base64 encoded string
+    FILE_URI: 1,         // Return file uri (content://media/external/images/media/2 for Android)
+    NATIVE_URI: 2        // Return native uri (eg. asset-library://... for iOS)
+  },
+  EncodingType:{
+    JPEG: 0,             // Return JPEG encoded image
+    PNG: 1               // Return PNG encoded image
+  },
+  MediaType:{
+    PICTURE: 0,          // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
+    VIDEO: 1,            // allow selection of video only, ONLY RETURNS URL
+    ALLMEDIA : 2         // allow selection from all media types
+  },
+  PictureSourceType:{
+    PHOTOLIBRARY : 0,    // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
+    CAMERA : 1,          // Take picture from camera
+    SAVEDPHOTOALBUM : 2  // Choose image from picture library (same as PHOTOLIBRARY for Android)
+  },
+  PopoverArrowDirection:{
+      ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants to specify arrow location on popover
+      ARROW_DOWN : 2,
+      ARROW_LEFT : 4,
+      ARROW_RIGHT : 8,
+      ARROW_ANY : 15
+  },
+  Direction:{
+      BACK: 0,
+      FRONT: 1
+  }
+};
+
+});
+
+// file: lib\common\plugin\CameraPopoverHandle.js
+define("cordova/plugin/CameraPopoverHandle", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+
+/**
+ * A handle to an image picker popover.
+ */
+var CameraPopoverHandle = function() {
+    this.setPosition = function(popoverOptions) {
+        console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
+
+// file: lib\common\plugin\CameraPopoverOptions.js
+define("cordova/plugin/CameraPopoverOptions", function(require, exports, module) {
+
+var Camera = require('cordova/plugin/CameraConstants');
+
+/**
+ * Encapsulates options for iOS Popover image picker
+ */
+var CameraPopoverOptions = function(x,y,width,height,arrowDir){
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    // The direction of the popover arrow
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
+
+// file: lib\common\plugin\CaptureAudioOptions.js
+define("cordova/plugin/CaptureAudioOptions", function(require, exports, module) {
+
+/**
+ * Encapsulates all audio capture operation configuration options.
+ */
+var CaptureAudioOptions = function(){
+    // Upper limit of sound clips user can record. Value must be equal or greater than 1.
+    this.limit = 1;
+    // Maximum duration of a single sound clip in seconds.
+    this.duration = 0;
+    // The selected audio mode. Must match with one of the elements in supportedAudioModes array.
+    this.mode = null;
+};
+
+module.exports = CaptureAudioOptions;
+
+});
+
+// file: lib\common\plugin\CaptureError.js
+define("cordova/plugin/CaptureError", function(require, exports, module) {
+
+/**
+ * The CaptureError interface encapsulates all errors in the Capture API.
+ */
+var CaptureError = function(c) {
+   this.code = c || null;
+};
+
+// Camera or microphone failed to capture image or sound.
+CaptureError.CAPTURE_INTERNAL_ERR = 0;
+// Camera application or audio capture application is currently serving other capture request.
+CaptureError.CAPTURE_APPLICATION_BUSY = 1;
+// Invalid use of the API (e.g. limit parameter has value less than one).
+CaptureError.CAPTURE_INVALID_ARGUMENT = 2;
+// User exited camera application or audio capture application before capturing anything.
+CaptureError.CAPTURE_NO_MEDIA_FILES = 3;
+// The requested capture operation is not supported.
+CaptureError.CAPTURE_NOT_SUPPORTED = 20;
+
+module.exports = CaptureError;
+
+});
+
+// file: lib\common\plugin\CaptureImageOptions.js
+define("cordova/plugin/CaptureImageOptions", function(require, exports, module) {
+
+/**
+ * Encapsulates all image capture operation configuration options.
+ */
+var CaptureImageOptions = function(){
+    // Upper limit of images user can take. Value must be equal or greater than 1.
+    this.limit = 1;
+    // The selected image mode. Must match with one of the elements in supportedImageModes array.
+    this.mode = null;
+};
+
+module.exports = CaptureImageOptions;
+
+});
+
+// file: lib\common\plugin\CaptureVideoOptions.js
+define("cordova/plugin/CaptureVideoOptions", function(require, exports, module) {
+
+/**
+ * Encapsulates all video capture operation configuration options.
+ */
+var CaptureVideoOptions = function(){
+    // Upper limit of videos user can record. Value must be equal or greater than 1.
+    this.limit = 1;
+    // Maximum duration of a single video clip in seconds.
+    this.duration = 0;
+    // The selected video mode. Must match with one of the elements in supportedVideoModes array.
+    this.mode = null;
+};
+
+module.exports = CaptureVideoOptions;
+
+});
+
+// file: lib\common\plugin\CompassError.js
+define("cordova/plugin/CompassError", function(require, exports, module) {
+
+/**
+ *  CompassError.
+ *  An error code assigned by an implementation when an error has occurred
+ * @constructor
+ */
+var CompassError = function(err) {
+    this.code = (err !== undefined ? err : null);
+};
+
+CompassError.COMPASS_INTERNAL_ERR = 0;
+CompassError.COMPASS_NOT_SUPPORTED = 20;
+
+module.exports = CompassError;
+
+});
+
+// file: lib\common\plugin\CompassHeading.js
+define("cordova/plugin/CompassHeading", function(require, exports, module) {
+
+var CompassHeading = function(magneticHeading, trueHeading, headingAccuracy, timestamp) {
+  this.magneticHeading = magneticHeading;
+  this.trueHeading = trueHeading;
+  this.headingAccuracy = headingAccuracy;
+  this.timestamp = timestamp || new Date().getTime();
+};
+
+module.exports = CompassHeading;
+
+});
+
+// file: lib\common\plugin\ConfigurationData.js
+define("cordova/plugin/ConfigurationData", function(require, exports, module) {
+
+/**
+ * Encapsulates a set of parameters that the capture device supports.
+ */
+function ConfigurationData() {
+    // The ASCII-encoded string in lower case representing the media type.
+    this.type = null;
+    // The height attribute represents height of the image or video in pixels.
+    // In the case of a sound clip this attribute has value 0.
+    this.height = 0;
+    // The width attribute represents width of the image or video in pixels.
+    // In the case of a sound clip this attribute has value 0
+    this.width = 0;
+}
+
+module.exports = ConfigurationData;
+
+});
+
+// file: lib\common\plugin\Connection.js
+define("cordova/plugin/Connection", function(require, exports, module) {
+
+/**
+ * Network status
+ */
+module.exports = {
+        UNKNOWN: "unknown",
+        ETHERNET: "ethernet",
+        WIFI: "wifi",
+        CELL_2G: "2g",
+        CELL_3G: "3g",
+        CELL_4G: "4g",
+        CELL:"cellular",
+        NONE: "none"
+};
+
+});
+
+// file: lib\common\plugin\Contact.js
+define("cordova/plugin/Contact", function(require, exports, module) {
+
+var argscheck = require('cordova/argscheck'),
+    exec = require('cordova/exec'),
+    ContactError = require('cordova/plugin/ContactError'),
+    utils = require('cordova/utils');
+
+/**
+* Converts primitives into Complex Object
+* Currently only used for Date fields
+*/
+function convertIn(contact) {
+    var value = contact.birthday;
+    try {
+      contact.birthday = new Date(parseFloat(value));
+    } catch (exception){
+      console.log("Cordova Contact convertIn error: exception creating date.");
+    }
+    return contact;
+}
+
+/**
+* Converts Complex objects into primitives
+* Only conversion at present is for Dates.
+**/
+
+function convertOut(contact) {
+    var value = contact.birthday;
+    if (value !== null) {
+        // try to make it a Date object if it is not already
+        if (!utils.isDate(value)){
+            try {
+                value = new Date(value);
+            } catch(exception){
+                value = null;
+            }
+        }
+        if (utils.isDate(value)){
+            value = value.valueOf(); // convert to milliseconds
+        }
+        contact.birthday = value;
+    }
+    return contact;
+}
+
+/**
+* Contains information about a single contact.
+* @constructor
+* @param {DOMString} id unique identifier
+* @param {DOMString} displayName
+* @param {ContactName} name
+* @param {DOMString} nickname
+* @param {Array.<ContactField>} phoneNumbers array of phone numbers
+* @param {Array.<ContactField>} emails array of email addresses
+* @param {Array.<ContactAddress>} addresses array of addresses
+* @param {Array.<ContactField>} ims instant messaging user ids
+* @param {Array.<ContactOrganization>} organizations
+* @param {DOMString} birthday contact's birthday
+* @param {DOMString} note user notes about contact
+* @param {Array.<ContactField>} photos
+* @param {Array.<ContactField>} categories
+* @param {Array.<ContactField>} urls contact's web sites
+*/
+var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
+    ims, organizations, birthday, note, photos, categories, urls) {
+    this.id = id || null;
+    this.rawId = null;
+    this.displayName = displayName || null;
+    this.name = name || null; // ContactName
+    this.nickname = nickname || null;
+    this.phoneNumbers = phoneNumbers || null; // ContactField[]
+    this.emails = emails || null; // ContactField[]
+    this.addresses = addresses || null; // ContactAddress[]
+    this.ims = ims || null; // ContactField[]
+    this.organizations = organizations || null; // ContactOrganization[]
+    this.birthday = birthday || null;
+    this.note = note || null;
+    this.photos = photos || null; // ContactField[]
+    this.categories = categories || null; // ContactField[]
+    this.urls = urls || null; // ContactField[]
+};
+
+/**
+* Removes contact from device storage.
+* @param successCB success callback
+* @param errorCB error callback
+*/
+Contact.prototype.remove = function(successCB, errorCB) {
+    argscheck.checkArgs('FF', 'Contact.remove', arguments);
+    var fail = errorCB && function(code) {
+        errorCB(new ContactError(code));
+    };
+    if (this.id === null) {
+        fail(ContactError.UNKNOWN_ERROR);
+    }
+    else {
+        exec(successCB, fail, "org.apache.cordova.core.contacts", "remove", [this.id]);
+    }
+};
+
+/**
+* Creates a deep copy of this Contact.
+* With the contact ID set to null.
+* @return copy of this Contact
+*/
+Contact.prototype.clone = function() {
+    var clonedContact = utils.clone(this);
+    clonedContact.id = null;
+    clonedContact.rawId = null;
+
+    function nullIds(arr) {
+        if (arr) {
+            for (var i = 0; i < arr.length; ++i) {
+                arr[i].id = null;
+            }
+        }
+    }
+
+    // Loop through and clear out any id's in phones, emails, etc.
+    nullIds(clonedContact.phoneNumbers);
+    nullIds(clonedContact.emails);
+    nullIds(clonedContact.addresses);
+    nullIds(clonedContact.ims);
+    nullIds(clonedContact.organizations);
+    nullIds(clonedContact.categories);
+    nullIds(clonedContact.photos);
+    nullIds(clonedContact.urls);
+    return clonedContact;
+};
+
+/**
+* Persists contact to device storage.
+* @param successCB success callback
+* @param errorCB error callback
+*/
+Contact.prototype.save = function(successCB, errorCB) {
+    argscheck.checkArgs('FFO', 'Contact.save', arguments);
+    var fail = errorCB && function(code) {
+        errorCB(new ContactError(code));
+    };
+    var success = function(result) {
+        if (result) {
+            if (successCB) {
+                var fullContact = require('cordova/plugin/contacts').create(result);
+                successCB(convertIn(fullContact));
+            }
+        }
+        else {
+            // no Entry object returned
+            fail(ContactError.UNKNOWN_ERROR);
+        }
+    };
+    var dupContact = convertOut(utils.clone(this));
+    exec(success, fail, "org.apache.cordova.core.contacts", "save", [dupContact]);
+};
+
+
+module.exports = Contact;
+
+});
+
+// file: lib\common\plugin\ContactAddress.js
+define("cordova/plugin/ContactAddress", function(require, exports, module) {
+
+/**
+* Contact address.
+* @constructor
+* @param {DOMString} id unique identifier, should only be set by native code
+* @param formatted // NOTE: not a W3C standard
+* @param streetAddress
+* @param locality
+* @param region
+* @param postalCode
+* @param country
+*/
+
+var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) {
+    this.id = null;
+    this.pref = (typeof pref != 'undefined' ? pref : false);
+    this.type = type || null;
+    this.formatted = formatted || null;
+    this.streetAddress = streetAddress || null;
+    this.locality = locality || null;
+    this.region = region || null;
+    this.postalCode = postalCode || null;
+    this.country = country || null;
+};
+
+module.exports = ContactAddress;
+
+});
+
+// file: lib\common\plugin\ContactError.js
+define("cordova/plugin/ContactError", function(require, exports, module) {
+
+/**
+ *  ContactError.
+ *  An error code assigned by an implementation when an error has occurred
+ * @constructor
+ */
+var ContactError = function(err) {
+    this.code = (typeof err != 'undefined' ? err : null);
+};
+
+/**
+ * Error codes
+ */
+ContactError.UNKNOWN_ERROR = 0;
+ContactError.INVALID_ARGUMENT_ERROR = 1;
+ContactError.TIMEOUT_ERROR = 2;
+ContactError.PENDING_OPERATION_ERROR = 3;
+ContactError.IO_ERROR = 4;
+ContactError.NOT_SUPPORTED_ERROR = 5;
+ContactError.PERMISSION_DENIED_ERROR = 20;
+
+module.exports = ContactError;
+
+});
+
+// file: lib\common\plugin\ContactField.js
+define("cordova/plugin/ContactField", function(require, exports, module) {
+
+/**
+* Generic contact field.
+* @constructor
+* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
+* @param type
+* @param value
+* @param pref
+*/
+var ContactField = function(type, value, pref) {
+    this.id = null;
+    this.type = (type && type.toString()) || null;
+    this.value = (value && value.toString()) || null;
+    this.pref = (typeof pref != 'undefined' ? pref : false);
+};
+
+module.exports = ContactField;
+
+});
+
+// file: lib\common\plugin\ContactFindOptions.js
+define("cordova/plugin/ContactFindOptions", function(require, exports, module) {
+
+/**
+ * ContactFindOptions.
+ * @constructor
+ * @param filter used to match contacts against
+ * @param multiple boolean used to determine if more than one contact should be returned
+ */
+
+var ContactFindOptions = function(filter, multiple) {
+    this.filter = filter || '';
+    this.multiple = (typeof multiple != 'undefined' ? multiple : false);
+};
+
+module.exports = ContactFindOptions;
+
+});
+
+// file: lib\common\plugin\ContactName.js
+define("cordova/plugin/ContactName", function(require, exports, module) {
+
+/**
+* Contact name.
+* @constructor
+* @param formatted // NOTE: not part of W3C standard
+* @param familyName
+* @param givenName
+* @param middle
+* @param prefix
+* @param suffix
+*/
+var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) {
+    this.formatted = formatted || null;
+    this.familyName = familyName || null;
+    this.givenName = givenName || null;
+    this.middleName = middle || null;
+    this.honorificPrefix = prefix || null;
+    this.honorificSuffix = suffix || null;
+};
+
+module.exports = ContactName;
+
+});
+
+// file: lib\common\plugin\ContactOrganization.js
+define("cordova/plugin/ContactOrganization", function(require, exports, module) {
+
+/**
+* Contact organization.
+* @constructor
+* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
+* @param name
+* @param dept
+* @param title
+* @param startDate
+* @param endDate
+* @param location
+* @param desc
+*/
+
+var ContactOrganization = function(pref, type, name, dept, title) {
+    this.id = null;
+    this.pref = (typeof pref != 'undefined' ? pref : false);
+    this.type = type || null;
+    this.name = name || null;
+    this.department = dept || null;
+    this.title = title || null;
+};
+
+module.exports = ContactOrganization;
+
+});
+
+// file: lib\common\plugin\Coordinates.js
+define("cordova/plugin/Coordinates", function(require, exports, module) {
+
+/**
+ * This class contains position information.
+ * @param {Object} lat
+ * @param {Object} lng
+ * @param {Object} alt
+ * @param {Object} acc
+ * @param {Object} head
+ * @param {Object} vel
+ * @param {Object} altacc
+ * @constructor
+ */
+var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) {
+    /**
+     * The latitude of the position.
+     */
+    this.latitude = lat;
+    /**
+     * The longitude of the position,
+     */
+    this.longitude = lng;
+    /**
+     * The accuracy of the position.
+     */
+    this.accuracy = acc;
+    /**
+     * The altitude of the position.
+     */
+    this.altitude = (alt !== undefined ? alt : null);
+    /**
+     * The direction the device is moving at the position.
+     */
+    this.heading = (head !== undefined ? head : null);
+    /**
+     * The velocity with which the device is moving at the position.
+     */
+    this.speed = (vel !== undefined ? vel : null);
+
+    if (this.speed === 0 || this.speed === null) {
+        this.heading = NaN;
+    }
+
+    /**
+     * The altitude accuracy of the position.
+     */
+    this.altitudeAccuracy = (altacc !== undefined) ? altacc : null;
+};
+
+module.exports = Coordinates;
+
+});
+
+// file: lib\common\plugin\DirectoryEntry.js
+define("cordova/plugin/DirectoryEntry", function(require, exports, module) {
+
+var argscheck = require('cordova/argscheck'),
+    utils = require('cordova/utils'),
+    exec = require('cordova/exec'),
+    Entry = require('cordova/plugin/Entry'),
+    FileError = require('cordova/plugin/FileError'),
+    DirectoryReader = require('cordova/plugin/DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * TODO: implement this!!! {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function(name, fullPath) {
+     DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function() {
+    return new DirectoryReader(this.fullPath);
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var win = successCallback && function(result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, "File", "getDirectory", [this.fullPath, path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, "File", "removeRecursively", [this.fullPath]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var win = successCallback && function(result) {
+        var FileEntry = require('cordova/plugin/FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, "File", "getFile", [this.fullPath, path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
+
+// file: lib\common\plugin\DirectoryReader.js
+define("cordova/plugin/DirectoryReader", function(require, exports, module) {
+
+var exec = require('cordova/exec'),
+    FileError = require('cordova/plugin/FileError') ;
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader(path) {
+    this.path = path || null;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
+    var win = typeof successCallback !== 'function' ? null : function(result) {
+        var retVal = [];
+        for (var i=0; i<result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('cordova/plugin/DirectoryEntry'))();
+            }
+            else if (result[i].isFile) {
+                entry = new (require('cordova/plugin/FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            retVal.push(entry);
+        }
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, "File", "readEntries", [this.path]);
+};
+
+module.exports = DirectoryReader;
+
+});
+
+// file: lib\common\plugin\Entry.js
+define("cordova/plugin/Entry", function(require, exports, module) {
+
+var argscheck = require('cordova/argscheck'),
+    exec = require('cordova/exec'),
+    FileError = require('cordova/plugin/FileError'),
+    Metadata = require('cordova/plugin/Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ */
+function Entry(isFile, isDirectory, name, fullPath, fileSystem) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function(successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function(lastModified) {
+        var metadata = new Metadata(lastModified);
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+
+    exec(success, fail, "File", "getMetadata", [this.fullPath]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, "File", "setMetadata", [this.fullPath, metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    // source path
+    var srcPath = this.fullPath,
+        // entry name
+        name = newName || this.name,
+        success = function(entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var result = (entry.isDirectory) ? new (require('cordova/plugin/DirectoryEntry'))(entry.name, entry.fullPath) : new (require('cordova/plugin/FileEntry'))(entry.name, entry.fullPath);
+                    successCallback(result);
+                }
+            }
+            else {
+                // no Entry object returned
+                fail && fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+    // copy
+    exec(success, fail, "File", "moveTo", [srcPath, parent.fullPath, name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+
+        // source path
+    var srcPath = this.fullPath,
+        // entry name
+        name = newName || this.name,
+        // success callback
+        success = function(entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var result = (entry.isDirectory) ? new (require('cordova/plugin/DirectoryEntry'))(entry.name, entry.fullPath) : new (require('cordova/plugin/FileEntry'))(entry.name, entry.fullPath);
+                    successCallback(result);
+                }
+            }
+            else {
+                // no Entry object returned
+                fail && fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+    // copy
+    exec(success, fail, "File", "copyTo", [srcPath, parent.fullPath, name]);
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ */
+Entry.prototype.toURL = function() {
+    // fullPath attribute contains the full URL
+    return this.fullPath;
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function(mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    // fullPath attribute contains the full URI
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function(successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, "File", "remove", [this.fullPath]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function(successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var win = successCallback && function(result) {
+        var DirectoryEntry = require('cordova/plugin/DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, "File", "getParent", [this.fullPath]);
+};
+
+module.exports = Entry;
+
+});
+
+// file: lib\common\plugin\File.js
+define("cordova/plugin/File", function(require, exports, module) {
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function(name, fullPath, type, lastModifiedDate, size){
+    this.name = name || '';
+    this.fullPath = fullPath || null;
+    this.type = type || null;
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function(start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.fullPath, this.type, this.lastModifiedData, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+
+module.exports = File;
+
+});
+
+// file: lib\common\plugin\FileEntry.js
+define("cordova/plugin/FileEntry", function(require, exports, module) {
+
+var utils = require('cordova/utils'),
+    exec = require('cordova/exec'),
+    Entry = require('cordova/plugin/Entry'),
+    FileWriter = require('cordova/plugin/FileWriter'),
+    File = require('cordova/plugin/File'),
+    FileError = require('cordova/plugin/FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function(name, fullPath) {
+     FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
+    this.file(function(filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.fileName === null || writer.fileName === "") {
+            errorCallback && errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+        } else {
+            successCallback && successCallback(writer);
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function(successCallback, errorCallback) {
+    var win = successCallback && function(f) {
+        var file = new File(f.name, f.fullPath, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function(code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, "File", "getFileMetadata", [this.fullPath]);
+};
+
+
+module.exports = FileEntry;
+
+});
+
+// file: lib\common\plugin\FileError.js
+define("cordova/plugin/FileError", function(require, exports, module) {
+
+/**
+ * FileError
+ */
+function FileError(error) {
+  this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
+
+// file: lib\common\plugin\FileReader.js
+define("cordova/plugin/FileReader", function(require, exports, module) {
+
+var exec = require('cordova/exec'),
+    modulemapper = require('cordova/modulemapper'),
+    utils = require('cordova/utils'),
+    File = require('cordova/plugin/File'),
+    FileError = require('cordova/plugin/FileError'),
+    ProgressEvent = require('cordova/plugin/ProgressEvent'),
+    origFileReader = modulemapper.getOriginalSymbol(this, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function() {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._fileName = '';
+    this._realReader = origFileReader ? new origFileReader() : {};
+};
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function() {
+    return this._fileName ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function() {
+    return this._fileName ? this._error: this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function() {
+    return this._fileName ? this._result: this._realReader.result;
+});
+
+function defineEvent(eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function() {
+        return this._realReader[eventName] || null;
+    }, function(value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead(reader, file) {
+    // Already loading something
+    if (reader.readyState == FileReader.LOADING) {
+      throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file == 'string') {
+        // Deprecated in Cordova 2.4.
+        console.warning('Using a string argument with FileReader.readAs functions is deprecated.');
+        reader._fileName = file;
+    } else if (typeof file.fullPath == 'string') {
+        reader._fileName = file.fullPath;
+    } else {
+        reader._fileName = '';
+        return true;
+    }
+
+    reader.onloadstart && reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function() {
+    if (origFileReader && !this._fileName) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
+      return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target:this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target:this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function(file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding ? encoding : "UTF-8";
+    var me = this;
+    var execArgs = [this._fileName, enc, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // Save result
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            // null result
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsText", execArgs);
+};
+
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function(file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var me = this;
+    var execArgs = [this._fileName, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            // Save result
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsDataURL", execArgs);
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function(file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var me = this;
+    var execArgs = [this._fileName, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsBinaryString", execArgs);
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function(file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var me = this;
+    var execArgs = [this._fileName, file.start, file.end];
+
+    // Read file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = r;
+
+            // If onload callback
+            if (typeof me.onload === "function") {
+                me.onload(new ProgressEvent("load", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me._readyState === FileReader.DONE) {
+                return;
+            }
+
+            // DONE state
+            me._readyState = FileReader.DONE;
+
+            me._result = null;
+
+            // Save error
+            me._error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {target:me}));
+            }
+
+            // If onloadend callback
+            if (typeof me.onloadend === "function") {
+                me.onloadend(new ProgressEvent("loadend", {target:me}));
+            }
+        }, "File", "readAsArrayBuffer", execArgs);
+};
+
+module.exports = FileReader;
+
+});
+
+// file: lib\common\plugin\FileSystem.js
+define("cordova/plugin/FileSystem", function(require, exports, module) {
+
+var DirectoryEntry = require('cordova/plugin/DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function(name, root) {
+    this.name = name || null;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath);
+    }
+};
+
+module.exports = FileSystem;
+
+});
+
+// file: lib\common\plugin\FileTransfer.js
+define("cordova/plugin/FileTransfer", function(require, exports, module) {
+
+var argscheck = require('cordova/argscheck'),
+    exec = require('cordova/exec'),
+    FileTransferError = require('cordova/plugin/FileTransferError'),
+    ProgressEvent = require('cordova/plugin/ProgressEvent');
+
+function newProgressEvent(result) {
+    var pe = new ProgressEvent();
+    pe.lengthComputable = result.lengthComputable;
+    pe.loaded = result.loaded;
+    pe.total = result.total;
+    return pe;
+}
+
+function getBasicAuthHeader(urlString) {
+    var header =  null;
+
+    if (window.btoa) {
+        // parse the url using the Location object
+        var url = document.createElement('a');
+        url.href = urlString;
+
+        var credentials = null;
+        var protocol = url.protocol + "//";
+        var origin = protocol + url.host;
+
+        // check whether there are the username:password credentials in the url
+        if (url.href.indexOf(origin) != 0) { // credentials found
+            var atIndex = url.href.indexOf("@");
+            credentials = url.href.substring(protocol.length, atIndex);
+        }
+
+        if (credentials) {
+            var authHeader = "Authorization";
+            var authHeaderValue = "Basic " + window.btoa(credentials);
+
+            header = {
+                name : authHeader,
+                value : authHeaderValue
+            };
+        }
+    }
+
+    return header;
+}
+
+var idCounter = 0;
+
+/**
+ * FileTransfer uploads a file to a remote server.
+ * @constructor
+ */
+var FileTransfer = function() {
+    this._id = ++idCounter;
+    this.onprogress = null; // optional callback
+};
+
+/**
+* Given an absolute file path, uploads a file on the device to a remote server
+* using a multipart HTTP request.
+* @param filePath {String}           Full path of the file on the device
+* @param server {String}             URL of the server to receive the file
+* @param successCallback (Function}  Callback to be invoked when upload has completed
+* @param errorCallback {Function}    Callback to be invoked upon error
+* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
+* @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
+*/
+FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) {
+    argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments);
+    // check for options
+    var fileKey = null;
+    var fileName = null;
+    var mimeType = null;
+    var params = null;
+    var chunkedMode = true;
+    var headers = null;
+
+    var basicAuthHeader = getBasicAuthHeader(server);
+    if (basicAuthHeader) {
+        if (!options) {
+            options = new FileUploadOptions();
+        }
+        if (!options.headers) {
+            options.headers = {};
+        }
+        options.headers[basicAuthHeader.name] = basicAuthHeader.value;
+    }
+
+    if (options) {
+        fileKey = options.fileKey;
+        fileName = options.fileName;
+        mimeType = options.mimeType;
+        headers = options.headers;
+        if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") {
+            chunkedMode = options.chunkedMode;
+        }
+        if (options.params) {
+            params = options.params;
+        }
+        else {
+            params = {};
+        }
+    }
+
+    var fail = errorCallback && function(e) {
+        var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body);
+        errorCallback(error);
+    };
+
+    var self = this;
+    var win = function(result) {
+        if (typeof result.lengthComputable != "undefined") {
+            if (self.onprogress) {
+                self.onprogress(newProgressEvent(result));
+            }
+        } else {
+            successCallback && successCallback(result);
+        }
+    };
+    exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id]);
+};
+
+/**
+ * Downloads a file form a given URL and saves it to the specified directory.
+ * @param source {String}          URL of the server to receive the file
+ * @param target {String}         Full path of the file on the device
+ * @param successCallback (Function}  Callback to be invoked when upload has completed
+ * @param errorCallback {Function}    Callback to be invoked upon error
+ * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
+ * @param options {FileDownloadOptions} Optional parameters such as headers
+ */
+FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts, options) {
+    argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments);
+    var self = this;
+
+    var basicAuthHeader = getBasicAuthHeader(source);
+    if (basicAuthHeader) {
+        if (!options) {
+            options = {};
+        }
+        if (!options.headers) {
+            options.headers

<TRUNCATED>

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


[03/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/css/index.css b/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
new file mode 100644
index 0000000..51daa79
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+* {
+    -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
+}
+
+body {
+    -webkit-touch-callout: none;                /* prevent callout to copy image, etc when tap to hold */
+    -webkit-text-size-adjust: none;             /* prevent webkit from resizing text to fit */
+    -webkit-user-select: none;                  /* prevent copy paste, to allow, change 'none' to 'text' */
+    background-color:#E4E4E4;
+    background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-webkit-gradient(
+        linear,
+        left top,
+        left bottom,
+        color-stop(0, #A7A7A7),
+        color-stop(0.51, #E4E4E4)
+    );
+    background-attachment:fixed;
+    font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
+    font-size:12px;
+    height:100%;
+    margin:0px;
+    padding:0px;
+    text-transform:uppercase;
+    width:100%;
+}
+
+/* Portrait layout (default) */
+.app {
+    background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
+    position:absolute;             /* position in the center of the screen */
+    left:50%;
+    top:50%;
+    height:50px;                   /* text area height */
+    width:225px;                   /* text area width */
+    text-align:center;
+    padding:180px 0px 0px 0px;     /* image height is 200px (bottom 20px are overlapped with text) */
+    margin:-115px 0px 0px -112px;  /* offset vertical: half of image height and text area height */
+                                   /* offset horizontal: half of text area width */
+}
+
+/* Landscape layout (with min-width) */
+@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
+    .app {
+        background-position:left center;
+        padding:75px 0px 75px 170px;  /* padding-top + padding-bottom + text area = image height */
+        margin:-90px 0px 0px -198px;  /* offset vertical: half of image height */
+                                      /* offset horizontal: half of image width and text area width */
+    }
+}
+
+h1 {
+    font-size:24px;
+    font-weight:normal;
+    margin:0px;
+    overflow:visible;
+    padding:0px;
+    text-align:center;
+}
+
+.event {
+    border-radius:4px;
+    -webkit-border-radius:4px;
+    color:#FFFFFF;
+    font-size:12px;
+    margin:0px 30px;
+    padding:2px 0px;
+}
+
+.event.listening {
+    background-color:#333333;
+    display:block;
+}
+
+.event.received {
+    background-color:#4B946A;
+    display:none;
+}
+
+@keyframes fade {
+    from { opacity: 1.0; }
+    50% { opacity: 0.4; }
+    to { opacity: 1.0; }
+}
+ 
+@-webkit-keyframes fade {
+    from { opacity: 1.0; }
+    50% { opacity: 0.4; }
+    to { opacity: 1.0; }
+}
+ 
+.blink {
+    animation:fade 3000ms infinite;
+    -webkit-animation:fade 3000ms infinite;
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png
new file mode 100644
index 0000000..86a48a8
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png
new file mode 100644
index 0000000..0e648ef
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png b/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png
new file mode 100644
index 0000000..d1e6c98
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png
new file mode 100644
index 0000000..dd00478
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/index.html
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/index.html b/cordova-common/spec/fixtures/projects/windows8/www/index.html
new file mode 100644
index 0000000..ca8ab84
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/index.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+    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.
+-->
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <meta name="format-detection" content="telephone=no" />
+        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
+        <link rel="stylesheet" type="text/css" href="css/index.css" />
+        <title>Hello World</title>
+    </head>
+    <body>
+        <div class="app">
+            <h1>Apache Cordova</h1>
+            <div id="deviceready" class="blink">
+                <p class="event listening">Connecting to Device</p>
+                <p class="event received">Device is Ready</p>
+            </div>
+        </div>
+        <script type="text/javascript" src="cordova-2.6.0.js"></script>
+        <script type="text/javascript" src="js/index.js"></script>
+        <script type="text/javascript">
+            app.initialize();
+        </script>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/js/index.js b/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
new file mode 100644
index 0000000..87b5660
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
@@ -0,0 +1,49 @@
+/*
+ * 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 app = {
+    // Application Constructor
+    initialize: function() {
+        this.bindEvents();
+    },
+    // Bind Event Listeners
+    //
+    // Bind any events that are required on startup. Common events are:
+    // 'load', 'deviceready', 'offline', and 'online'.
+    bindEvents: function() {
+        document.addEventListener('deviceready', this.onDeviceReady, false);
+    },
+    // deviceready Event Handler
+    //
+    // The scope of 'this' is the event. In order to call the 'receivedEvent'
+    // function, we must explicitly call 'app.receivedEvent(...);'
+    onDeviceReady: function() {
+        app.receivedEvent('deviceready');
+    },
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        var parentElement = document.getElementById(id);
+        var listeningElement = parentElement.querySelector('.listening');
+        var receivedElement = parentElement.querySelector('.received');
+
+        listeningElement.setAttribute('style', 'display:none;');
+        receivedElement.setAttribute('style', 'display:block;');
+
+        console.log('Received Event: ' + id);
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/test-config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/test-config.xml b/cordova-common/spec/fixtures/test-config.xml
new file mode 100644
index 0000000..ac22580
--- /dev/null
+++ b/cordova-common/spec/fixtures/test-config.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>Hello Cordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <preference name="fullscreen" value="true" />
+    <preference name="webviewbounce" value="true" />
+    <preference name="orientation" value="portrait" />
+    <icon id="icon" src="icon.png" />
+    <icon height="255" id="logo" src="logo.png" width="255" />
+    <platform name="android">
+        <icon density="mdpi" height="255" src="logo-android.png" width="255" />
+        <preference name="android-minSdkVersion" value="10" />
+        <preference name="orientation" value="landscape" />
+    </platform>
+    <plugin name="org.apache.cordova.pluginwithvars">
+        <variable name="var" value="varvalue" />
+    </plugin>
+    <plugin name="org.apache.cordova.pluginwithurl" src="http://cordova.apache.org/pluginwithurl" />
+    <plugin name="org.apache.cordova.pluginwithversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.pluginwithurlandversion" src="http://cordova.apache.org/pluginwithurlandversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.justaplugin" />
+    <feature name="Legacy plugin entry with version">
+        <param name="id" value="org.apache.cordova.legacyfeatureversion" />
+        <param name="version" value="1.2.3" />
+        <param name="aVar" value="aValue" />
+    </feature>
+    <feature name="Legacy plugin entry with url">
+        <param name="id" value="org.apache.cordova.legacyfeatureurl" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureurl" />
+    </feature>
+    <feature name="Legacy plugin entry with version and url">
+        <param name="id" value="org.apache.cordova.legacyfeatureversionandurl" />
+        <param name="version" value="1.2.3" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureversionandurl" />
+    </feature>
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/util/xml-helpers.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/util/xml-helpers.spec.js b/cordova-common/spec/util/xml-helpers.spec.js
new file mode 100644
index 0000000..8cc46ca
--- /dev/null
+++ b/cordova-common/spec/util/xml-helpers.spec.js
@@ -0,0 +1,271 @@
+/**
+    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.
+*/
+
+/* jshint laxcomma: true, multistr: true */
+
+var path = require('path')
+  , xml_helpers = require('../../src/util/xml-helpers')
+  , et = require('elementtree')
+
+  , title = et.XML('<title>HELLO</title>')
+  , usesNetworkOne = et.XML('<uses-permission ' +
+            'android:name="PACKAGE_NAME.permission.C2D_MESSAGE"/>')
+  , usesNetworkTwo = et.XML('<uses-permission android:name=\
+            "PACKAGE_NAME.permission.C2D_MESSAGE" />')
+  , usesReceive = et.XML('<uses-permission android:name=\
+            "com.google.android.c2dm.permission.RECEIVE"/>')
+  , helloTagOne = et.XML('<h1>HELLO</h1>')
+  , goodbyeTag = et.XML('<h1>GOODBYE</h1>')
+  , helloTagTwo = et.XML('<h1>  HELLO  </h1>');
+
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+    '<widget xmlns     = "http://www.w3.org/ns/widgets"\n' +
+    '        xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+    '        id        = "io.cordova.hellocordova"\n' +
+    '        version   = "0.0.1">\n' +
+    '    <name>Hello Cordova</name>\n' +
+    '    <description>\n' +
+    '        A sample Apache Cordova application that responds to the deviceready event.\n' +
+    '    </description>\n' +
+    '    <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+    '        Apache Cordova Team\n' +
+    '    </author>\n' +
+    '    <content src="index.html" />\n' +
+    '    <access origin="*" />\n' +
+    '    <preference name="fullscreen" value="true" />\n' +
+    '    <preference name="webviewbounce" value="true" />\n' +
+    '</widget>\n';
+
+describe('xml-helpers', function(){
+    describe('parseElementtreeSync', function() {
+        it('should parse xml with a byte order mark', function() {
+            var xml_path = path.join(__dirname, '../fixtures/projects/windows/bom_test.xml');
+            expect(function() {
+                xml_helpers.parseElementtreeSync(xml_path);
+            }).not.toThrow();
+        });
+    });
+    describe('equalNodes', function() {
+        it('should return false for different tags', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, title)).toBe(false);
+        });
+
+        it('should return true for identical tags', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, usesNetworkTwo)).toBe(true);
+        });
+
+        it('should return false for different attributes', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, usesReceive)).toBe(false);
+        });
+
+        it('should distinguish between text', function(){
+            expect(xml_helpers.equalNodes(helloTagOne, goodbyeTag)).toBe(false);
+        });
+
+        it('should ignore whitespace in text', function(){
+            expect(xml_helpers.equalNodes(helloTagOne, helloTagTwo)).toBe(true);
+        });
+
+        describe('should compare children', function(){
+            it('by child quantity', function(){
+                var one = et.XML('<i><b>o</b></i>'),
+                    two = et.XML('<i><b>o</b><u></u></i>');
+
+                expect(xml_helpers.equalNodes(one, two)).toBe(false);
+            });
+
+            it('by child equality', function(){
+                var one = et.XML('<i><b>o</b></i>'),
+                    two = et.XML('<i><u></u></i>'),
+                    uno = et.XML('<i>\n<b>o</b>\n</i>');
+
+                expect(xml_helpers.equalNodes(one, uno)).toBe(true);
+                expect(xml_helpers.equalNodes(one, two)).toBe(false);
+            });
+        });
+    });
+    describe('pruneXML', function() {
+        var config_xml;
+
+        beforeEach(function() {
+            config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/projects/android/res/xml/config.xml'));
+        });
+
+        it('should remove any children that match the specified selector', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+        it('should do nothing if the children cannot be found', function() {
+            var children = [title];
+            xml_helpers.pruneXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(17);
+        });
+        it('should be able to handle absolute selectors', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, '/cordova/plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+        it('should be able to handle absolute selectors with wildcards', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, '/*/plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+    });
+
+    describe('graftXML', function() {
+        var config_xml, plugin_xml;
+
+        beforeEach(function() {
+            config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/projects/android/res/xml/config.xml'));
+            plugin_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/plugins/ChildBrowser/plugin.xml'));
+        });
+
+        it('should add children to the specified selector', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(19);
+        });
+        it('should be able to handle absolute selectors', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, '/cordova');
+            expect(config_xml.findall('access').length).toEqual(3);
+        });
+        it('should be able to handle absolute selectors with wildcards', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, '/*');
+            expect(config_xml.findall('access').length).toEqual(3);
+        });
+    });
+
+    describe('mergeXml', function () {
+        var dstXml;
+        beforeEach(function() {
+            dstXml = et.XML(TEST_XML);
+        });
+        it('should merge attributes and text of the root element without clobbering', function () {
+            var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+            xml_helpers.mergeXml(testXml, dstXml);
+            expect(dstXml.attrib.foo).toEqual('bar');
+            expect(dstXml.attrib.id).not.toEqual('NOTANID');
+            expect(dstXml.text).not.toEqual('TEXT');
+        });
+
+        it('should merge attributes and text of the root element with clobbering', function () {
+            var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            expect(dstXml.attrib.foo).toEqual('bar');
+            expect(dstXml.attrib.id).toEqual('NOTANID');
+            expect(dstXml.text).toEqual('TEXT');
+        });
+
+        it('should not merge platform tags with the wrong platform', function () {
+            var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+                origCfg = et.tostring(dstXml);
+
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            expect(et.tostring(dstXml)).toEqual(origCfg);
+        });
+
+        it('should merge platform tags with the correct platform', function () {
+            var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+                origCfg = et.tostring(dstXml);
+
+            xml_helpers.mergeXml(testXml, dstXml, 'bar', true);
+            expect(et.tostring(dstXml)).not.toEqual(origCfg);
+            var testElement = dstXml.find('testElement');
+            expect(testElement).toBeDefined();
+            expect(testElement.attrib.testAttrib).toEqual('value');
+            expect(testElement.text).toEqual('testTEXT');
+        });
+
+        it('should merge singelton children without clobber', function () {
+            var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml);
+            var testElements = dstXml.findall('author');
+            expect(testElements).toBeDefined();
+            expect(testElements.length).toEqual(1);
+            expect(testElements[0].attrib.testAttrib).toEqual('value');
+            expect(testElements[0].attrib.href).toEqual('http://cordova.io');
+            expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+            expect(testElements[0].text).toContain('Apache Cordova Team');
+        });
+
+        it('should clobber singelton children with clobber', function () {
+            var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('author');
+            expect(testElements).toBeDefined();
+            expect(testElements.length).toEqual(1);
+            expect(testElements[0].attrib.testAttrib).toEqual('value');
+            expect(testElements[0].attrib.href).toEqual('http://www.nowhere.com');
+            expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+            expect(testElements[0].text).toEqual('SUPER_AUTHOR');
+        });
+
+        it('should append non singelton children', function () {
+            var testXml = et.XML('<widget><preference num="1"/> <preference num="2"/></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('preference');
+            expect(testElements.length).toEqual(4);
+        });
+
+        it('should handle namespaced elements', function () {
+            var testXml = et.XML('<widget><foo:bar testAttrib="value">testText</foo:bar></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            var testElement = dstXml.find('foo:bar');
+            expect(testElement).toBeDefined();
+            expect(testElement.attrib.testAttrib).toEqual('value');
+            expect(testElement.text).toEqual('testText');
+        });
+
+        it('should not append duplicate non singelton children', function () {
+            var testXml = et.XML('<widget><preference name="fullscreen" value="true"/></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('preference');
+            expect(testElements.length).toEqual(2);
+        });
+
+        it('should not skip partial duplicate non singelton children', function () {
+            //remove access tags from dstXML
+            var testElements = dstXml.findall('access');
+            for(var i = 0; i < testElements.length; i++) {
+                dstXml.remove(testElements[i]);
+            }
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(0);
+            //add an external whitelist access tag
+            var testXml = et.XML('<widget><access origin="*" launch-external="yes"/></widget>');
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(1);
+            //add an internal whitelist access tag
+            testXml = et.XML('<widget><access origin="*"/></widget>');
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(2);
+
+        });
+    });
+});


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


[05/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

Posted by sg...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.pbxproj b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5630416
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
@@ -0,0 +1,496 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A463F14DB0A1B007FEAC7 /* Foundation.framework */; };
+		571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464114DB0A1B007FEAC7 /* UIKit.framework */; };
+		571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */; };
+		571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464514DB0A1B007FEAC7 /* AddressBook.framework */; };
+		571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */; };
+		571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */; };
+		571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */; };
+		571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */; };
+		571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */; };
+		571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465114DB0A1B007FEAC7 /* QuartzCore.framework */; };
+		571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */; };
+		571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */; };
+		571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465714DB0A1B007FEAC7 /* CoreMedia.framework */; };
+		571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */; };
+		571A466014DB0A1B007FEAC7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A465F14DB0A1B007FEAC7 /* main.m */; };
+		571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A466214DB0A1B007FEAC7 /* PhoneGap.framework */; };
+		571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466614DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466A14DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466F14DB0A1B007FEAC7 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A466E14DB0A1B007FEAC7 /* icon.png */; };
+		571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467014DB0A1B007FEAC7 /* icon@2x.png */; };
+		571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467214DB0A1B007FEAC7 /* icon-72.png */; };
+		571A467614DB0A1B007FEAC7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467514DB0A1B007FEAC7 /* Default.png */; };
+		571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467714DB0A1B007FEAC7 /* Default@2x.png */; };
+		571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 571A467914DB0A1B007FEAC7 /* Capture.bundle */; };
+		571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */ = {isa = PBXBuildFile; fileRef = 571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */; };
+		571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A467F14DB0A1B007FEAC7 /* AppDelegate.m */; };
+		571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A468214DB0A1B007FEAC7 /* MainViewController.m */; };
+		571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 571A468414DB0A1B007FEAC7 /* MainViewController.xib */; };
+		577FC36614DB0B620082BA7B /* www in Resources */ = {isa = PBXBuildFile; fileRef = 577FC36514DB0B620082BA7B /* www */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		571A463B14DB0A1B007FEAC7 /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		571A463F14DB0A1B007FEAC7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		571A464114DB0A1B007FEAC7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		571A464514DB0A1B007FEAC7 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+		571A465114DB0A1B007FEAC7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		571A465714DB0A1B007FEAC7 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		571A465B14DB0A1B007FEAC7 /* SampleApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SampleApp-Info.plist"; sourceTree = "<group>"; };
+		571A465D14DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		571A465F14DB0A1B007FEAC7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		571A466114DB0A1B007FEAC7 /* SampleApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SampleApp-Prefix.pch"; sourceTree = "<group>"; };
+		571A466214DB0A1B007FEAC7 /* PhoneGap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhoneGap.framework; path = /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework; sourceTree = "<absolute>"; };
+		571A466714DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Resources/en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466B14DB0A1B007FEAC7 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Resources/es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466E14DB0A1B007FEAC7 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon.png; path = Resources/icons/icon.png; sourceTree = "<group>"; };
+		571A467014DB0A1B007FEAC7 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon@2x.png"; path = "Resources/icons/icon@2x.png"; sourceTree = "<group>"; };
+		571A467214DB0A1B007FEAC7 /* icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-72.png"; path = "Resources/icons/icon-72.png"; sourceTree = "<group>"; };
+		571A467514DB0A1B007FEAC7 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/splash/Default.png; sourceTree = "<group>"; };
+		571A467714DB0A1B007FEAC7 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/splash/Default@2x.png"; sourceTree = "<group>"; };
+		571A467914DB0A1B007FEAC7 /* Capture.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Capture.bundle; path = Resources/Capture.bundle; sourceTree = "<group>"; };
+		571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PhoneGap.plist; sourceTree = "<group>"; };
+		571A467E14DB0A1B007FEAC7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = "<group>"; };
+		571A467F14DB0A1B007FEAC7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = "<group>"; };
+		571A468114DB0A1B007FEAC7 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = "<group>"; };
+		571A468214DB0A1B007FEAC7 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = "<group>"; };
+		571A468414DB0A1B007FEAC7 /* MainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainViewController.xib; path = Classes/MainViewController.xib; sourceTree = "<group>"; };
+		571A468714DB0A1B007FEAC7 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = Plugins/README; sourceTree = "<group>"; };
+		577FC36514DB0B620082BA7B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		571A463514DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */,
+				571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */,
+				571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */,
+				571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */,
+				571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */,
+				571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */,
+				571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */,
+				571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */,
+				571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */,
+				571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */,
+				571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */,
+				571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */,
+				571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */,
+				571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463814DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		571A462D14DB0A1A007FEAC7 = {
+			isa = PBXGroup;
+			children = (
+				577FC36514DB0B620082BA7B /* www */,
+				571A465914DB0A1B007FEAC7 /* SampleApp */,
+				571A463E14DB0A1B007FEAC7 /* Frameworks */,
+				571A463C14DB0A1B007FEAC7 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		571A463C14DB0A1B007FEAC7 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				571A463B14DB0A1B007FEAC7 /* SampleApp.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		571A463E14DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				571A463F14DB0A1B007FEAC7 /* Foundation.framework */,
+				571A464114DB0A1B007FEAC7 /* UIKit.framework */,
+				571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */,
+				571A464514DB0A1B007FEAC7 /* AddressBook.framework */,
+				571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */,
+				571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */,
+				571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */,
+				571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */,
+				571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */,
+				571A465114DB0A1B007FEAC7 /* QuartzCore.framework */,
+				571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */,
+				571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */,
+				571A465714DB0A1B007FEAC7 /* CoreMedia.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		571A465914DB0A1B007FEAC7 /* SampleApp */ = {
+			isa = PBXGroup;
+			children = (
+				571A466214DB0A1B007FEAC7 /* PhoneGap.framework */,
+				571A466414DB0A1B007FEAC7 /* Resources */,
+				571A467D14DB0A1B007FEAC7 /* Classes */,
+				571A468614DB0A1B007FEAC7 /* Plugins */,
+				571A465A14DB0A1B007FEAC7 /* Supporting Files */,
+			);
+			path = SampleApp;
+			sourceTree = "<group>";
+		};
+		571A465A14DB0A1B007FEAC7 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				571A465B14DB0A1B007FEAC7 /* SampleApp-Info.plist */,
+				571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */,
+				571A465F14DB0A1B007FEAC7 /* main.m */,
+				571A466114DB0A1B007FEAC7 /* SampleApp-Prefix.pch */,
+				571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */,
+				571A468414DB0A1B007FEAC7 /* MainViewController.xib */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		571A466414DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				571A467914DB0A1B007FEAC7 /* Capture.bundle */,
+				571A466514DB0A1B007FEAC7 /* en.lproj */,
+				571A466914DB0A1B007FEAC7 /* es.lproj */,
+				571A466D14DB0A1B007FEAC7 /* icons */,
+				571A467414DB0A1B007FEAC7 /* splash */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		571A466514DB0A1B007FEAC7 /* en.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466614DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = en.lproj;
+			sourceTree = "<group>";
+		};
+		571A466914DB0A1B007FEAC7 /* es.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466A14DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = es.lproj;
+			sourceTree = "<group>";
+		};
+		571A466D14DB0A1B007FEAC7 /* icons */ = {
+			isa = PBXGroup;
+			children = (
+				571A466E14DB0A1B007FEAC7 /* icon.png */,
+				571A467014DB0A1B007FEAC7 /* icon@2x.png */,
+				571A467214DB0A1B007FEAC7 /* icon-72.png */,
+			);
+			name = icons;
+			sourceTree = "<group>";
+		};
+		571A467414DB0A1B007FEAC7 /* splash */ = {
+			isa = PBXGroup;
+			children = (
+				571A467514DB0A1B007FEAC7 /* Default.png */,
+				571A467714DB0A1B007FEAC7 /* Default@2x.png */,
+			);
+			name = splash;
+			sourceTree = "<group>";
+		};
+		571A467D14DB0A1B007FEAC7 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				571A467E14DB0A1B007FEAC7 /* AppDelegate.h */,
+				571A467F14DB0A1B007FEAC7 /* AppDelegate.m */,
+				571A468114DB0A1B007FEAC7 /* MainViewController.h */,
+				571A468214DB0A1B007FEAC7 /* MainViewController.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		571A468614DB0A1B007FEAC7 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				571A468714DB0A1B007FEAC7 /* README */,
+			);
+			name = Plugins;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		571A463A14DB0A1B007FEAC7 /* SampleApp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "SampleApp" */;
+			buildPhases = (
+				571A463414DB0A1B007FEAC7 /* Sources */,
+				571A463514DB0A1B007FEAC7 /* Frameworks */,
+				571A463614DB0A1B007FEAC7 /* Resources */,
+				571A463714DB0A1B007FEAC7 /* Sources */,
+				571A463814DB0A1B007FEAC7 /* Frameworks */,
+				571A463914DB0A1B007FEAC7 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = SampleApp;
+			productName = SampleApp;
+			productReference = 571A463B14DB0A1B007FEAC7 /* SampleApp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		571A462F14DB0A1A007FEAC7 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0420;
+			};
+			buildConfigurationList = 571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "SampleApp" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				es,
+			);
+			mainGroup = 571A462D14DB0A1A007FEAC7;
+			productRefGroup = 571A463C14DB0A1B007FEAC7 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				571A463A14DB0A1B007FEAC7 /* SampleApp */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		571A463614DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */,
+				571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466F14DB0A1B007FEAC7 /* icon.png in Resources */,
+				571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */,
+				571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */,
+				571A467614DB0A1B007FEAC7 /* Default.png in Resources */,
+				571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */,
+				571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */,
+				571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */,
+				571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */,
+				577FC36614DB0B620082BA7B /* www in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		571A463914DB0A1B007FEAC7 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "\n\t\t\t\t\t\t\t\tif [ ! -d \"$PROJECT_DIR/www\" ] ; then\n\t\t\t\t\t\t\t\t\tcp -R /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework/www \"$PROJECT_DIR\"\n\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\t\t# detect www folder reference in project, if missing, print warning\n\t\t\t\t\t\t\t\tgrep \"{isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = \\\"<group>\\\"; };\" \"$PROJECT_DIR/$PROJECT_NAME.xcodeproj/project.pbxproj\"\n\t\t\t\t\t\t\t\trc=$? \n\t\t\t\t\t\t\t\tif [ $rc != 0 ] ; then\n\t\t\t\t\t\t\t\techo -e \"warning: Missing - Add $PROJECT_DIR/www as a folder reference in your project. Just drag and drop the folder into your project, into the Project Navigator of Xcode 4. Make sure you select the second radio-button: 'Create folder references for any added folders' (which will create a blue folder)\" 1>&2\n\t\t\t\t\t\t\t\tfi\t\t\t\t\t\t\t";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		571A463414DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A466014DB0A1B007FEAC7 /* main.m in Sources */,
+				571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */,
+				571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463714DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A465D14DB0A1B007FEAC7 /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		571A466614DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466714DB0A1B007FEAC7 /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		571A466A14DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466B14DB0A1B007FEAC7 /* es */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		571A468814DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		571A468914DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		571A468B14DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		571A468C14DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "SampleApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468814DB0A1B007FEAC7 /* Debug */,
+				571A468914DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "SampleApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468B14DB0A1B007FEAC7 /* Debug */,
+				571A468C14DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 571A462F14DB0A1A007FEAC7 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/SampleApp-Info.plist
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/SampleApp-Info.plist b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/SampleApp-Info.plist
new file mode 100644
index 0000000..1edf010
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/SampleApp-Info.plist
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+#
+# 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.
+#
+-->
+<plist version="1.0">
+<dict>
+	<key>CFBundleIcons</key>
+	<dict>
+		<key>CFBundlePrimaryIcon</key>
+		<dict>
+			<key>CFBundleIconFiles</key>
+			<array>
+                <string>icon.png</string>
+                <string>icon@2x.png</string>
+                <string>icon-72.png</string>
+                <string>icon-72@2x.png</string>
+			</array>
+			<key>UIPrerenderedIcon</key>
+			<false/>
+		</dict>
+	</dict>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>CFValidSchemas</key>
+	<array>
+		<string>schema-a</string>
+	</array>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>icon.png</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.example.friendstring</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSMainNibFile</key>
+	<string></string>
+	<key>NSMainNibFile~ipad</key>
+	<string></string>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/config.xml b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/config.xml
new file mode 100644
index 0000000..f0a823b
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/ios-config-xml/SampleApp/config.xml
@@ -0,0 +1,59 @@
+<?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>
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="UIWebViewBounce" value="true" />
+    <preference name="TopActivityIndicator" value="gray" />
+    <preference name="EnableLocation" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="ShowSplashScreenSpinner" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="OpenAllWhitelistURLsInWebView" value="false" />
+    <preference name="BackupWebStorage" value="cloud" />
+
+    <plugins>
+        <plugin name="Device" value="CDVDevice" />
+        <plugin name="Logger" value="CDVLogger" />
+        <plugin name="Compass" value="CDVLocation" />
+        <plugin name="Accelerometer" value="CDVAccelerometer" />
+        <plugin name="Camera" value="CDVCamera" />
+        <plugin name="NetworkStatus" value="CDVConnection" />
+        <plugin name="org.apache.cordova.core.contacts" value="CDVContacts" />
+        <plugin name="Debug Console" value="CDVDebugConsole" />
+        <plugin name="Echo" value="CDVEcho" />
+        <plugin name="File" value="CDVFile" />
+        <plugin name="FileTransfer" value="CDVFileTransfer" />
+        <plugin name="Geolocation" value="CDVLocation" />
+        <plugin name="Notification" value="CDVNotification" />
+        <plugin name="Media" value="CDVSound" />
+        <plugin name="Capture" value="CDVCapture" />
+        <plugin name="SplashScreen" value="CDVSplashScreen" />
+        <plugin name="Battery" value="CDVBattery" />
+        <plugin name="Globalization" value="CDVGlobalization" />
+        <plugin name="InAppBrowser" value="CDVInAppBrowser" />
+    </plugins>
+
+    <access origin="*" />
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/ios-config-xml/www/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/ios-config-xml/www/.gitkeep b/cordova-common/spec/fixtures/projects/ios-config-xml/www/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows/bom_test.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows/bom_test.xml b/cordova-common/spec/fixtures/projects/windows/bom_test.xml
new file mode 100644
index 0000000..57cadf6
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows/bom_test.xml
@@ -0,0 +1,24 @@
+<?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>
+    <access origin="*"/>
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/CordovaApp_TemporaryKey.pfx
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/CordovaApp_TemporaryKey.pfx b/cordova-common/spec/fixtures/projects/windows8/CordovaApp_TemporaryKey.pfx
new file mode 100644
index 0000000..4df1e37
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/CordovaApp_TemporaryKey.pfx differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/TestApp.jsproj
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/TestApp.jsproj b/cordova-common/spec/fixtures/projects/windows8/TestApp.jsproj
new file mode 100644
index 0000000..ff6cf68
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/TestApp.jsproj
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|AnyCPU">
+      <Configuration>Debug</Configuration>
+      <Platform>AnyCPU</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x86">
+      <Configuration>Debug</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|AnyCPU">
+      <Configuration>Release</Configuration>
+      <Platform>AnyCPU</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x86">
+      <Configuration>Release</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>efffab2f-bfc5-4eda-b545-45ef4995f55a</ProjectGuid>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '11.0'">
+    <VisualStudioVersion>11.0</VisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).props" />
+  <PropertyGroup>
+    <TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
+    <TargetPlatformVersion>8.0</TargetPlatformVersion>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <PackageCertificateKeyFile>CordovaApp_TemporaryKey.pfx</PackageCertificateKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <AppxManifest Include="package.appxmanifest">
+      <SubType>Designer</SubType>
+    </AppxManifest>
+    <Content Include="www\cordova-2.6.0.js" />
+    <Content Include="www\css\index.css" />
+    <Content Include="www\img\logo.png" />
+    <Content Include="www\img\smalllogo.png" />
+    <Content Include="www\img\splashscreen.png" />
+    <Content Include="www\img\storelogo.png" />
+    <Content Include="www\index.html" />
+    <Content Include="www\js\index.js" />
+    <None Include="CordovaApp_TemporaryKey.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <SDKReference Include="Microsoft.WinJS.1.0, Version=1.0" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
+  <!-- To modify your build process, add your task inside one of the targets below then uncomment
+       that target and the DisableFastUpToDateCheck PropertyGroup. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  <PropertyGroup>
+    <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+  </PropertyGroup>
+  -->
+</Project>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/TestApp.sln
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/TestApp.sln b/cordova-common/spec/fixtures/projects/windows8/TestApp.sln
new file mode 100644
index 0000000..6c1ea33
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/TestApp.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "TestApp", "TestApp.jsproj", "{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|ARM = Debug|ARM
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|ARM = Release|ARM
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|ARM.ActiveCfg = Debug|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|ARM.Build.0 = Debug|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|ARM.Deploy.0 = Debug|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x64.ActiveCfg = Debug|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x64.Build.0 = Debug|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x64.Deploy.0 = Debug|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x86.ActiveCfg = Debug|x86
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x86.Build.0 = Debug|x86
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Debug|x86.Deploy.0 = Debug|x86
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|ARM.ActiveCfg = Release|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|ARM.Build.0 = Release|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|ARM.Deploy.0 = Release|ARM
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x64.ActiveCfg = Release|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x64.Build.0 = Release|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x64.Deploy.0 = Release|x64
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x86.ActiveCfg = Release|x86
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x86.Build.0 = Release|x86
+		{EFFFAB2F-BFC5-4EDA-B545-45EF4995F55A}.Release|x86.Deploy.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/package.appxmanifest
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/package.appxmanifest b/cordova-common/spec/fixtures/projects/windows8/package.appxmanifest
new file mode 100644
index 0000000..0e69293
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/package.appxmanifest
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
+  <Identity Name="efffab2f-bfc5-4eda-b545-45ef4995f55a" Version="1.0.0.0" Publisher="CN=Jesse" />
+  <Properties>
+    <DisplayName>CordovaApp</DisplayName>
+    <PublisherDisplayName>Jesse</PublisherDisplayName>
+    <Logo>images\storelogo.png</Logo>
+  </Properties>
+  <Prerequisites>
+    <OSMinVersion>6.2.1</OSMinVersion>
+    <OSMaxVersionTested>6.2.1</OSMaxVersionTested>
+  </Prerequisites>
+  <Resources>
+    <Resource Language="x-generate" />
+  </Resources>
+  <Applications>
+    <Application Id="App" StartPage="www/index.html">
+      <VisualElements DisplayName="CordovaApp" Logo="www\img\logo.png" SmallLogo="www\img\smalllogo.png" Description="CordovaApp" ForegroundText="light" BackgroundColor="#464646">
+        <DefaultTile ShowName="allLogos" />
+        <SplashScreen Image="www\img\splashscreen.png" />
+      </VisualElements>
+    </Application>
+  </Applications>
+  <Capabilities>
+    <Capability Name="internetClient" />
+  </Capabilities>
+</Package>


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