You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pm...@apache.org on 2012/03/22 13:50:23 UTC

[6/12] 2nd try at file refactoring

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/FileWriter.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/FileWriter.js b/lib/common/plugin/FileWriter.js
new file mode 100644
index 0000000..e0e5626
--- /dev/null
+++ b/lib/common/plugin/FileWriter.js
@@ -0,0 +1,253 @@
+var exec = require('cordova/exec'),
+    FileError = require('cordova/plugin/FileError');
+    ProgressEvent = require('cordova/plugin/ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function(file) {
+    this.fileName = "";
+    this.length = 0;
+    if (file) {
+        this.fileName = file.fullPath || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function() {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === "function") {
+        this.onabort(new ProgressEvent("abort", {"target":this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === "function") {
+        this.onwriteend(new ProgressEvent("writeend", {"target":this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param text to be written
+ */
+FileWriter.prototype.write = function(text) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === "function") {
+        me.onwritestart(new ProgressEvent("writestart", {"target":me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === "function") {
+                me.onwrite(new ProgressEvent("write", {"target":me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === "function") {
+                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {"target":me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === "function") {
+                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
+            }
+        }, "File", "write", [this.fileName, text, this.position]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function(offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    }
+    // Offset is bigger then file size so set position
+    // to the end of the file.
+    else if (offset > this.length) {
+        this.position = this.length;
+    }
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function(size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === "function") {
+        me.onwritestart(new ProgressEvent("writestart", {"target":this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function(r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === "function") {
+                me.onwrite(new ProgressEvent("write", {"target":me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === "function") {
+                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
+            }
+        },
+        // Error callback
+        function(e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === "function") {
+                me.onerror(new ProgressEvent("error", {"target":me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === "function") {
+                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
+            }
+        }, "File", "truncate", [this.fileName, size]);
+};
+
+module.exports = FileWriter;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/Flags.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/Flags.js b/lib/common/plugin/Flags.js
new file mode 100644
index 0000000..d918c38
--- /dev/null
+++ b/lib/common/plugin/Flags.js
@@ -0,0 +1,15 @@
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ * 
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags(create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/LocalFileSystem.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/LocalFileSystem.js b/lib/common/plugin/LocalFileSystem.js
new file mode 100644
index 0000000..f71ae62
--- /dev/null
+++ b/lib/common/plugin/LocalFileSystem.js
@@ -0,0 +1,13 @@
+var exec = require('cordova/exec');
+
+/**
+ * Represents a local file system.
+ */
+var LocalFileSystem = function() {
+
+};
+
+LocalFileSystem.TEMPORARY = 0; //temporary, with no guarantee of persistence
+LocalFileSystem.PERSISTENT = 1; //persistent
+
+module.exports = LocalFileSystem;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/Media.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/Media.js b/lib/common/plugin/Media.js
new file mode 100644
index 0000000..8d56da9
--- /dev/null
+++ b/lib/common/plugin/Media.js
@@ -0,0 +1,186 @@
+var utils = require('cordova/utils'),
+    exec = require('cordova/exec');
+
+var mediaObjects = {};
+
+/**
+ * This class provides access to the device media, interfaces to both sound and video
+ *
+ * @constructor
+ * @param src                   The file name or url to play
+ * @param successCallback       The callback to be called when the file is done playing or recording.
+ *                                  successCallback()
+ * @param errorCallback         The callback to be called if there is an error.
+ *                                  errorCallback(int errorCode) - OPTIONAL
+ * @param statusCallback        The callback to be called when media status has changed.
+ *                                  statusCallback(int statusCode) - OPTIONAL
+ */
+var Media = function(src, successCallback, errorCallback, statusCallback) {
+
+    // successCallback optional
+    if (successCallback && (typeof successCallback !== "function")) {
+        console.log("Media Error: successCallback is not a function");
+        return;
+    }
+
+    // errorCallback optional
+    if (errorCallback && (typeof errorCallback !== "function")) {
+        console.log("Media Error: errorCallback is not a function");
+        return;
+    }
+
+    // statusCallback optional
+    if (statusCallback && (typeof statusCallback !== "function")) {
+        console.log("Media Error: statusCallback is not a function");
+        return;
+    }
+
+    this.id = utils.createUUID();
+    mediaObjects[this.id] = this;
+    this.src = src;
+    this.successCallback = successCallback;
+    this.errorCallback = errorCallback;
+    this.statusCallback = statusCallback;
+    this._duration = -1;
+    this._position = -1;
+    exec(null, this.errorCallback, "Media", "create", [this.id, this.src]);
+};
+
+// Media messages
+Media.MEDIA_STATE = 1;
+Media.MEDIA_DURATION = 2;
+Media.MEDIA_POSITION = 3;
+Media.MEDIA_ERROR = 9;
+
+// Media states
+Media.MEDIA_NONE = 0;
+Media.MEDIA_STARTING = 1;
+Media.MEDIA_RUNNING = 2;
+Media.MEDIA_PAUSED = 3;
+Media.MEDIA_STOPPED = 4;
+Media.MEDIA_MSG = ["None", "Starting", "Running", "Paused", "Stopped"];
+
+// "static" function to return existing objs.
+Media.get = function(id) {
+    return mediaObjects[id];
+};
+
+/**
+ * Start or resume playing audio file.
+ */
+Media.prototype.play = function() {
+    exec(this.successCallback, this.errorCallback, "Media", "startPlayingAudio", [this.id, this.src]);
+};
+
+/**
+ * Stop playing audio file.
+ */
+Media.prototype.stop = function() {
+    var me = this;
+    exec(function() {
+        me._position = 0;
+        me.successCallback();
+    }, this.errorCallback, "Media", "stopPlayingAudio", [this.id]);
+};
+
+/**
+ * Seek or jump to a new time in the track..
+ */
+Media.prototype.seekTo = function(milliseconds) {
+    var me = this;
+    exec(function(p) {
+        me._position = p;
+    }, this.errorCallback, "Media", "seekToAudio", [this.id, milliseconds]);
+};
+
+/**
+ * Pause playing audio file.
+ */
+Media.prototype.pause = function() {
+    exec(null, this.errorCallback, "Media", "pausePlayingAudio", [this.id]);
+};
+
+/**
+ * Get duration of an audio file.
+ * The duration is only set for audio that is playing, paused or stopped.
+ *
+ * @return      duration or -1 if not known.
+ */
+Media.prototype.getDuration = function() {
+    return this._duration;
+};
+
+/**
+ * Get position of audio.
+ */
+Media.prototype.getCurrentPosition = function(success, fail) {
+    var me = this;
+    exec(function(p) {
+        me._position = p;
+        success(p);
+    }, fail, "Media", "getCurrentPositionAudio", [this.id]);
+};
+
+/**
+ * Start recording audio file.
+ */
+Media.prototype.startRecord = function() {
+    exec(this.successCallback, this.errorCallback, "Media", "startRecordingAudio", [this.id, this.src]);
+};
+
+/**
+ * Stop recording audio file.
+ */
+Media.prototype.stopRecord = function() {
+    exec(this.successCallback, this.errorCallback, "Media", "stopRecordingAudio", [this.id]);
+};
+
+/**
+ * Release the resources.
+ */
+Media.prototype.release = function() {
+    exec(null, this.errorCallback, "Media", "release", [this.id]);
+};
+
+/**
+ * Adjust the volume.
+ */
+Media.prototype.setVolume = function(volume) {
+    exec(null, null, "Media", "setVolume", [this.id, volume]);
+};
+
+/**
+ * Audio has status update.
+ * PRIVATE
+ *
+ * @param id            The media object id (string)
+ * @param status        The status code (int)
+ * @param msg           The status message (string)
+ */
+Media.onStatus = function(id, msg, value) {
+    var media = mediaObjects[id];
+    // If state update
+    if (msg === Media.MEDIA_STATE) {
+        if (value === Media.MEDIA_STOPPED) {
+            if (media.successCallback) {
+                media.successCallback();
+            }
+        }
+        if (media.statusCallback) {
+            media.statusCallback(value);
+        }
+    }
+    else if (msg === Media.MEDIA_DURATION) {
+        media._duration = value;
+    }
+    else if (msg === Media.MEDIA_ERROR) {
+        if (media.errorCallback) {
+            media.errorCallback({"code":value});
+        }
+    }
+    else if (msg === Media.MEDIA_POSITION) {
+        media._position = value;
+    }
+};
+
+module.exports = Media;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/MediaError.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/MediaError.js b/lib/common/plugin/MediaError.js
new file mode 100644
index 0000000..40ce8f1
--- /dev/null
+++ b/lib/common/plugin/MediaError.js
@@ -0,0 +1,16 @@
+/**
+ * This class contains information about any Media errors.
+ * @constructor
+ */
+var MediaError = function(code, msg) {
+    this.code = (code !== undefined ? code : null);
+    this.message = msg || "";
+};
+
+MediaError.MEDIA_ERR_NONE_ACTIVE    = 0;
+MediaError.MEDIA_ERR_ABORTED        = 1;
+MediaError.MEDIA_ERR_NETWORK        = 2;
+MediaError.MEDIA_ERR_DECODE         = 3;
+MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
+
+module.exports = MediaError;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/MediaFile.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/MediaFile.js b/lib/common/plugin/MediaFile.js
new file mode 100644
index 0000000..e73716b
--- /dev/null
+++ b/lib/common/plugin/MediaFile.js
@@ -0,0 +1,56 @@
+var utils = require('cordova/utils'),
+    exec = require('cordova/exec'),
+    File = require('cordova/plugin/File'),
+    CaptureError = require('cordova/plugin/CaptureError');
+/**
+ * Represents a single file.
+ *
+ * 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 MediaFile = function(name, fullPath, type, lastModifiedDate, size){
+  MediaFile.__super__.constructor.apply(this, arguments);
+};
+
+utils.extend(MediaFile, File);
+
+/**
+ * Request capture format data for a specific file and type
+ * 
+ * @param {Function} successCB
+ * @param {Function} errorCB
+ */
+MediaFile.prototype.getFormatData = function(successCallback, errorCallback) {
+	if (typeof this.fullPath === "undefined" || this.fullPath === null) {
+		errorCallback(new CaptureError(CaptureError.CAPTURE_INVALID_ARGUMENT));
+	} else {
+    exec(successCallback, errorCallback, "Capture", "getFormatData", [this.fullPath, this.type]);
+	}	
+};
+
+/**
+ * Casts a PluginResult message property  (array of objects) to an array of MediaFile objects
+ * (used in Objective-C and Android)
+ *
+ * @param {PluginResult} pluginResult
+ */
+MediaFile.cast = function(pluginResult) {
+  var mediaFiles = [];
+  var i;
+  for (i=0; i<pluginResult.message.length; i++) {
+    var mediaFile = new MediaFile();
+    mediaFile.name = pluginResult.message[i].name;
+    mediaFile.fullPath = pluginResult.message[i].fullPath;
+    mediaFile.type = pluginResult.message[i].type;
+    mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate;
+    mediaFile.size = pluginResult.message[i].size;
+    mediaFiles.push(mediaFile);
+  }
+  pluginResult.message = mediaFiles;
+  return pluginResult;
+};
+
+module.exports = MediaFile;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/MediaFileData.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/MediaFileData.js b/lib/common/plugin/MediaFileData.js
new file mode 100644
index 0000000..ea5c2a3
--- /dev/null
+++ b/lib/common/plugin/MediaFileData.js
@@ -0,0 +1,18 @@
+/**
+ * MediaFileData encapsulates format information of a media file.
+ *
+ * @param {DOMString} codecs
+ * @param {long} bitrate
+ * @param {long} height
+ * @param {long} width
+ * @param {float} duration
+ */
+var MediaFileData = function(codecs, bitrate, height, width, duration){
+	this.codecs = codecs || null;
+	this.bitrate = bitrate || 0;
+	this.height = height || 0;
+	this.width = width || 0;
+	this.duration = duration || 0;
+};
+
+module.exports = MediaFileData;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/Metadata.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/Metadata.js b/lib/common/plugin/Metadata.js
new file mode 100644
index 0000000..b29cc7c
--- /dev/null
+++ b/lib/common/plugin/Metadata.js
@@ -0,0 +1,10 @@
+/**
+ * Information about the state of the file or directory
+ * 
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function(time) {
+    this.modificationTime = (typeof time != 'undefined'?new Date(time):null);
+};
+
+module.exports = Metadata;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/Position.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/Position.js b/lib/common/plugin/Position.js
new file mode 100644
index 0000000..25096c4
--- /dev/null
+++ b/lib/common/plugin/Position.js
@@ -0,0 +1,8 @@
+var Coordinates = require('cordova/plugin/Coordinates');
+
+var Position = function(coords, timestamp) {
+	this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy);
+	this.timestamp = (timestamp !== undefined) ? timestamp : new Date().getTime();
+};
+
+module.exports = Position;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/PositionError.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/PositionError.js b/lib/common/plugin/PositionError.js
new file mode 100644
index 0000000..07012d6
--- /dev/null
+++ b/lib/common/plugin/PositionError.js
@@ -0,0 +1,17 @@
+/**
+ * Position error object
+ *
+ * @constructor
+ * @param code
+ * @param message
+ */
+var PositionError = function(code, message) {
+    this.code = code || null;
+    this.message = message || '';
+};
+
+PositionError.PERMISSION_DENIED = 1;
+PositionError.POSITION_UNAVAILABLE = 2;
+PositionError.TIMEOUT = 3;
+
+module.exports = PositionError;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/ProgressEvent.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/ProgressEvent.js b/lib/common/plugin/ProgressEvent.js
new file mode 100644
index 0000000..d8e41c1
--- /dev/null
+++ b/lib/common/plugin/ProgressEvent.js
@@ -0,0 +1,46 @@
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function() {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+        return function ProgressEvent(type, dict) {
+            this.type = type;
+            this.bubbles = false;
+            this.cancelBubble = false;
+            this.cancelable = false;
+            this.lengthComputable = false;
+            this.loaded = dict && dict.loaded ? dict.loaded : 0;
+            this.total = dict && dict.total ? dict.total : 0;
+            this.target = dict && dict.target ? dict.target : null;
+        };
+    //}
+})();
+
+module.exports = ProgressEvent;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/accelerometer.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/accelerometer.js b/lib/common/plugin/accelerometer.js
new file mode 100644
index 0000000..6f01ab8
--- /dev/null
+++ b/lib/common/plugin/accelerometer.js
@@ -0,0 +1,95 @@
+/**
+ * This class provides access to device accelerometer data.
+ * @constructor
+ */
+var utils = require("cordova/utils"),
+    exec = require("cordova/exec");
+
+// Local singleton variables.
+var timers = {};
+
+var accelerometer = {
+    /**
+     * Asynchronously aquires the current acceleration.
+     *
+     * @param {Function} successCallback    The function to call when the acceleration data is available
+     * @param {Function} errorCallback      The function to call when there is an error getting the acceleration data. (OPTIONAL)
+     * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
+     */
+    getCurrentAcceleration: function(successCallback, errorCallback, options) {
+
+        // successCallback required
+        if (typeof successCallback !== "function") {
+            console.log("Accelerometer Error: successCallback is not a function");
+            return;
+        }
+
+        // errorCallback optional
+        if (errorCallback && (typeof errorCallback !== "function")) {
+            console.log("Accelerometer Error: errorCallback is not a function");
+            return;
+        }
+
+        // Get acceleration
+        exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []);
+    },
+
+    /**
+     * Asynchronously aquires the acceleration repeatedly at a given interval.
+     *
+     * @param {Function} successCallback    The function to call each time the acceleration data is available
+     * @param {Function} errorCallback      The function to call when there is an error getting the acceleration data. (OPTIONAL)
+     * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
+     * @return String                       The watch id that must be passed to #clearWatch to stop watching.
+     */
+    watchAcceleration: function(successCallback, errorCallback, options) {
+
+        // Default interval (10 sec)
+        var frequency = (options !== undefined && options.frequency !== undefined)? options.frequency : 10000;
+
+        // successCallback required
+        if (typeof successCallback !== "function") {
+            console.log("Accelerometer Error: successCallback is not a function");
+            return;
+        }
+
+        // errorCallback optional
+        if (errorCallback && (typeof errorCallback !== "function")) {
+            console.log("Accelerometer Error: errorCallback is not a function");
+            return;
+        }
+
+        // Make sure accelerometer timeout > frequency + 10 sec
+        exec(
+            function(timeout) {
+                if (timeout < (frequency + 10000)) {
+                    exec(null, null, "Accelerometer", "setTimeout", [frequency + 10000]);
+                }
+            },
+            function(e) { }, "Accelerometer", "getTimeout", []);
+
+        // Start watch timer
+        var id = utils.createUUID();
+        timers[id] = window.setInterval(function() {
+            exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []);
+        }, (frequency ? frequency : 1));
+
+        return id;
+    },
+
+    /**
+     * Clears the specified accelerometer watch.
+     *
+     * @param {String} id       The id of the watch returned from #watchAcceleration.
+     */
+    clearWatch: function(id) {
+
+        // Stop javascript timer & remove from timer list
+        if (id && timers[id] !== undefined) {
+            window.clearInterval(timers[id]);
+            delete timers[id];
+        }
+    }
+};
+
+module.exports = accelerometer;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/battery.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/battery.js b/lib/common/plugin/battery.js
new file mode 100644
index 0000000..5649356
--- /dev/null
+++ b/lib/common/plugin/battery.js
@@ -0,0 +1,87 @@
+/**
+ * This class contains information about the current battery status.
+ * @constructor
+ */
+var cordova = require('cordova'),
+    exec = require('cordova/exec');
+
+function handlers() {
+  return battery.channels.batterystatus.numHandlers + 
+         battery.channels.batterylow.numHandlers +
+         battery.channels.batterycritical.numHandlers;
+}
+
+var Battery = function() {
+    this._level = null;
+    this._isPlugged = null;
+    // Create new event handlers on the window (returns a channel instance)
+    var subscriptionEvents = {
+      onSubscribe:this.onSubscribe,
+      onUnsubscribe:this.onUnsubscribe
+    };
+    this.channels = {
+      batterystatus:cordova.addWindowEventHandler("batterystatus", subscriptionEvents),
+      batterylow:cordova.addWindowEventHandler("batterylow", subscriptionEvents),
+      batterycritical:cordova.addWindowEventHandler("batterycritical", subscriptionEvents)
+    };
+};
+/**
+ * Event handlers for when callbacks get registered for the battery.
+ * Keep track of how many handlers we have so we can start and stop the native battery listener
+ * appropriately (and hopefully save on battery life!).
+ */
+Battery.prototype.onSubscribe = function() {
+  var me = battery;
+  // If we just registered the first handler, make sure native listener is started.
+  if (handlers() === 1) {
+    exec(me._status, me._error, "Battery", "start", []);
+  }
+};
+
+Battery.prototype.onUnsubscribe = function() {
+  var me = battery;
+
+  // If we just unregistered the last handler, make sure native listener is stopped.
+  if (handlers() === 0) {
+      exec(null, null, "Battery", "stop", []);
+  }
+};
+
+/**
+ * Callback for battery status
+ * 
+ * @param {Object} info			keys: level, isPlugged
+ */
+Battery.prototype._status = function(info) {
+	if (info) {
+		var me = battery;
+    var level = info.level;
+		if (me._level !== level || me._isPlugged !== info.isPlugged) {
+			// Fire batterystatus event
+			cordova.fireWindowEvent("batterystatus", info);
+
+			// Fire low battery event
+			if (level === 20 || level === 5) {
+				if (level === 20) {
+					cordova.fireWindowEvent("batterylow", info);
+				}
+				else {
+					cordova.fireWindowEvent("batterycritical", info);
+				}
+			}
+		}
+		me._level = level;
+		me._isPlugged = info.isPlugged;	
+	}
+};
+
+/**
+ * Error callback for battery start
+ */
+Battery.prototype._error = function(e) {
+    console.log("Error initializing Battery: " + e);
+};
+
+var battery = new Battery();
+
+module.exports = battery;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/capture.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/capture.js b/lib/common/plugin/capture.js
new file mode 100644
index 0000000..e088ba6
--- /dev/null
+++ b/lib/common/plugin/capture.js
@@ -0,0 +1,72 @@
+var exec = require('cordova/exec'),
+    MediaFile = require('cordova/plugin/MediaFile');
+
+/**
+ * Launches a capture of different types.
+ *
+ * @param (DOMString} type 
+ * @param {Function} successCB
+ * @param {Function} errorCB
+ * @param {CaptureVideoOptions} options
+ */
+function _capture(type, successCallback, errorCallback, options) {
+    var win = function(pluginResult) {
+        var mediaFiles = [];
+        var i;
+        for (i = 0; i < pluginResult.length; i++) {
+            var mediaFile = new MediaFile();
+            mediaFile.name = pluginResult[i].name;
+            mediaFile.fullPath = pluginResult[i].fullPath;
+            mediaFile.type = pluginResult[i].type;
+            mediaFile.lastModifiedDate = pluginResult[i].lastModifiedDate;
+            mediaFile.size = pluginResult[i].size;
+            mediaFiles.push(mediaFile);
+        }
+        successCallback(mediaFiles);
+    };
+    exec(win, errorCallback, "Capture", type, [options]);
+}
+/**
+ * The Capture interface exposes an interface to the camera and microphone of the hosting device.
+ */
+function Capture() {
+	this.supportedAudioModes = [];
+	this.supportedImageModes = [];
+	this.supportedVideoModes = [];
+}
+
+/**
+ * Launch audio recorder application for recording audio clip(s).
+ *
+ * @param {Function} successCB
+ * @param {Function} errorCB
+ * @param {CaptureAudioOptions} options
+ */
+Capture.prototype.captureAudio = function(successCallback, errorCallback, options){
+    _capture("captureAudio", successCallback, errorCallback, options);
+};
+
+/**
+ * Launch camera application for taking image(s).
+ *
+ * @param {Function} successCB
+ * @param {Function} errorCB
+ * @param {CaptureImageOptions} options
+ */
+Capture.prototype.captureImage = function(successCallback, errorCallback, options){
+    _capture("captureImage", successCallback, errorCallback, options);
+};
+
+/**
+ * Launch device camera application for recording video(s).
+ *
+ * @param {Function} successCB
+ * @param {Function} errorCB
+ * @param {CaptureVideoOptions} options
+ */
+Capture.prototype.captureVideo = function(successCallback, errorCallback, options){
+    _capture("captureVideo", successCallback, errorCallback, options);
+};
+
+
+module.exports = new Capture();

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/compass.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/compass.js b/lib/common/plugin/compass.js
new file mode 100644
index 0000000..1685f2d
--- /dev/null
+++ b/lib/common/plugin/compass.js
@@ -0,0 +1,90 @@
+var exec = require('cordova/exec'),
+    utils = require('cordova/utils'),
+    CompassHeading = require('cordova/plugin/CompassHeading'),
+    CompassError = require('cordova/plugin/CompassError'),
+    timers = {},
+    compass = {
+        /**
+         * Asynchronously acquires the current heading.
+         * @param {Function} successCallback The function to call when the heading
+         * data is available
+         * @param {Function} errorCallback The function to call when there is an error 
+         * getting the heading data.
+         * @param {CompassOptions} options The options for getting the heading data (not used).
+         */
+        getCurrentHeading:function(successCallback, errorCallback) {
+            // successCallback required
+            if (typeof successCallback !== "function") {
+              console.log("Compass Error: successCallback is not a function");
+              return;
+            }
+
+            // errorCallback optional
+            if (errorCallback && (typeof errorCallback !== "function")) {
+              console.log("Compass Error: errorCallback is not a function");
+              return;
+            }
+
+            var win = function(result) {
+                var ch = new CompassHeading(result.magneticHeading, result.trueHeading, result.headingAccuracy, result.timestamp);
+                successCallback(ch);
+            };
+            var fail = function(code) {
+                var ce = new CompassError(code);
+                errorCallback(ce);
+            }
+            
+            // Get heading
+            exec(win, fail, "Compass", "getHeading", []);
+        },
+
+        /**
+         * Asynchronously acquires the heading repeatedly at a given interval.
+         * @param {Function} successCallback The function to call each time the heading
+         * data is available
+         * @param {Function} errorCallback The function to call when there is an error 
+         * getting the heading data.
+         * @param {HeadingOptions} options The options for getting the heading data
+         * such as timeout and the frequency of the watch.
+         */
+        watchHeading:function(successCallback, errorCallback, options) {
+            // Default interval (100 msec)
+            var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100;
+
+            // successCallback required
+            if (typeof successCallback !== "function") {
+              console.log("Compass Error: successCallback is not a function");
+              return;
+            }
+
+            // errorCallback optional
+            if (errorCallback && (typeof errorCallback !== "function")) {
+              console.log("Compass Error: errorCallback is not a function");
+              return;
+            }
+
+            // Start watch timer to get headings
+            var id = utils.createUUID();
+
+            timers[id] = window.setInterval(function() {
+                compass.getCurrentHeading(successCallback, errorCallback);
+            }, frequency);
+
+            return id;
+        },
+
+        /**
+         * Clears the specified heading watch.
+         * @param {String} watchId The ID of the watch returned from #watchHeading.
+         */
+        clearWatch:function(id) {
+            // Stop javascript timer & remove from timer list
+            if (id && timers[id]) {
+              clearInterval(timers[id]);
+              delete timers[id];
+            }
+        }
+        // TODO: add the filter-based iOS-only methods
+    };
+
+module.exports = compass;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/contacts.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/contacts.js b/lib/common/plugin/contacts.js
new file mode 100644
index 0000000..7212f7b
--- /dev/null
+++ b/lib/common/plugin/contacts.js
@@ -0,0 +1,57 @@
+var exec = require('cordova/exec'),
+    ContactError = require('cordova/plugin/ContactError'),
+    Contact = require('cordova/plugin/Contact');
+
+/**
+* Represents a group of Contacts.
+* @constructor
+*/
+var contacts = {
+    /**
+     * Returns an array of Contacts matching the search criteria.
+     * @param fields that should be searched
+     * @param successCB success callback
+     * @param errorCB error callback
+     * @param {ContactFindOptions} options that can be applied to contact searching
+     * @return array of Contacts matching search criteria
+     */
+    find:function(fields, successCB, errorCB, options) {
+        if (!successCB) {
+            throw new TypeError("You must specify a success callback for the find command.");
+        }
+        if (!fields || (fields instanceof Array && fields.length === 0)) {
+            if (typeof errorCB === "function") {
+                errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
+            }
+        } else {
+            var win = function(result) {
+                var cs = [];
+                for (var i = 0, l = result.length; i < l; i++) {
+                    cs.push(contacts.create(result[i]));
+                }
+                successCB(cs);
+            };
+            exec(win, errorCB, "Contacts", "search", [fields, options]);
+        }
+    },
+
+    /**
+     * This function creates a new contact, but it does not persist the contact
+     * to device storage. To persist the contact to device storage, invoke
+     * contact.save().
+     * @param properties an object who's properties will be examined to create a new Contact
+     * @returns new Contact object
+     */
+    create:function(properties) {
+        var i;
+        var contact = new Contact();
+        for (i in properties) {
+            if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
+                contact[i] = properties[i];
+            }
+        }
+        return contact;
+    }
+};
+
+module.exports = contacts;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/geolocation.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/geolocation.js b/lib/common/plugin/geolocation.js
new file mode 100644
index 0000000..e1169f6
--- /dev/null
+++ b/lib/common/plugin/geolocation.js
@@ -0,0 +1,94 @@
+var utils = require('cordova/utils'),
+    exec = require('cordova/exec'),
+    PositionError = require('cordova/plugin/PositionError'),
+    Position = require('cordova/plugin/Position');
+
+var timers = {};   // list of timers in use
+
+// Returns default params, overrides if provided with values
+function parseParameters(options) {
+    var opt = {
+        maximumAge: 10000,
+        enableHighAccuracy: false,
+        timeout: 10000
+    };
+
+    if (options) {
+        if (options.maximumAge !== undefined) {
+            opt.maximumAge = options.maximumAge;
+        }
+        if (options.enableHighAccuracy !== undefined) {
+            opt.enableHighAccuracy = options.enableHighAccuracy;
+        }
+        if (options.timeout !== undefined) {
+            opt.timeout = options.timeout;
+        }
+    }
+
+    return opt;
+}
+
+var geolocation = {
+    /**
+   * Asynchronously aquires the current position.
+   *
+   * @param {Function} successCallback    The function to call when the position data is available
+   * @param {Function} errorCallback      The function to call when there is an error getting the heading position. (OPTIONAL)
+   * @param {PositionOptions} options     The options for getting the position data. (OPTIONAL)
+   */
+    getCurrentPosition:function(successCallback, errorCallback, options) {
+        options = parseParameters(options);
+
+        var win = function(p) {
+            successCallback(new Position(
+                {
+                    latitude:p.latitude,
+                    longitude:p.longitude,
+                    altitude:p.altitude,
+                    accuracy:p.accuracy,
+                    heading:p.heading,
+                    velocity:p.velocity,
+                    altitudeAccuracy:p.altitudeAccuracy
+                },
+                p.timestamp || new Date()
+            ));
+        };
+        var fail = function(e) {
+            errorCallback(new PositionError(e.code, e.message));
+        };
+
+        exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]); 
+    },
+    /**
+     * Asynchronously watches the geolocation for changes to geolocation.  When a change occurs,
+     * the successCallback is called with the new location.
+     *
+     * @param {Function} successCallback    The function to call each time the location data is available
+     * @param {Function} errorCallback      The function to call when there is an error getting the location data. (OPTIONAL)
+     * @param {PositionOptions} options     The options for getting the location data such as frequency. (OPTIONAL)
+     * @return String                       The watch id that must be passed to #clearWatch to stop watching.
+     */
+    watchPosition:function(successCallback, errorCallback, options) {
+        options = parseParameters(options);
+
+        var id = utils.createUUID();
+        timers[id] = window.setInterval(function() {
+            geolocation.getCurrentPosition(successCallback, errorCallback, options);
+        }, options.timeout);
+
+        return id;
+    },
+    /**
+     * Clears the specified heading watch.
+     *
+     * @param {String} id       The ID of the watch returned from #watchPosition
+     */
+    clearWatch:function(id) {
+        if (id && timers[id] !== undefined) {
+            window.clearInterval(timers[id]);
+            delete timers[id];
+        }
+    }
+};
+
+module.exports = geolocation;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/network.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/network.js b/lib/common/plugin/network.js
new file mode 100644
index 0000000..29e1aee
--- /dev/null
+++ b/lib/common/plugin/network.js
@@ -0,0 +1,59 @@
+var exec = require('cordova/exec'),
+    cordova = require('cordova'),
+    channel = require('cordova/channel');
+
+var NetworkConnection = function () {
+        this.type = null;
+        this._firstRun = true;
+        this._timer = null;
+        this.timeout = 500;
+
+        var me = this;
+
+        this.getInfo(
+            function (info) {
+                me.type = info;
+                if (info === "none") {
+                    // set a timer if still offline at the end of timer send the offline event
+                    me._timer = setTimeout(function(){
+                        cordova.fireDocumentEvent("offline");
+                        me._timer = null;
+                        }, me.timeout);
+                } else {
+                    // If there is a current offline event pending clear it
+                    if (me._timer !== null) {
+                        clearTimeout(me._timer);
+                        me._timer = null;
+                    }
+                    cordova.fireDocumentEvent("online");
+                }
+
+                // should only fire this once
+                if (me._firstRun) {
+                    me._firstRun = false;
+                    channel.onCordovaConnectionReady.fire();
+                }
+            },
+            function (e) {
+                // If we can't get the network info we should still tell Cordova
+                // to fire the deviceready event.
+                if (me._firstRun) {
+                    me._firstRun = false;
+                    channel.onCordovaConnectionReady.fire();
+                }
+                console.log("Error initializing Network Connection: " + e);
+            });
+};
+
+/**
+ * Get connection info
+ *
+ * @param {Function} successCallback The function to call when the Connection data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL)
+ */
+NetworkConnection.prototype.getInfo = function (successCallback, errorCallback) {
+    // Get info
+    exec(successCallback, errorCallback, "Network Status", "getConnectionInfo", []);
+};
+
+module.exports = new NetworkConnection();

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/notification.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/notification.js b/lib/common/plugin/notification.js
new file mode 100644
index 0000000..305ee3d
--- /dev/null
+++ b/lib/common/plugin/notification.js
@@ -0,0 +1,56 @@
+var exec = require('cordova/exec');
+
+/**
+ * Provides access to notifications on the device.
+ */
+
+module.exports = {
+
+    /**
+     * Open a native alert dialog, with a customizable title and button text.
+     *
+     * @param {String} message              Message to print in the body of the alert
+     * @param {Function} completeCallback   The callback that is called when user clicks on a button.
+     * @param {String} title                Title of the alert dialog (default: Alert)
+     * @param {String} buttonLabel          Label of the close button (default: OK)
+     */
+    alert: function(message, completeCallback, title, buttonLabel) {
+        var _title = (title || "Alert");
+        var _buttonLabel = (buttonLabel || "OK");
+        exec(completeCallback, null, "Notification", "alert", [message, _title, _buttonLabel]);
+    },
+
+    /**
+     * Open a native confirm dialog, with a customizable title and button text.
+     * The result that the user selects is returned to the result callback.
+     *
+     * @param {String} message              Message to print in the body of the alert
+     * @param {Function} resultCallback     The callback that is called when user clicks on a button.
+     * @param {String} title                Title of the alert dialog (default: Confirm)
+     * @param {String} buttonLabels         Comma separated list of the labels of the buttons (default: 'OK,Cancel')
+     */
+    confirm: function(message, resultCallback, title, buttonLabels) {
+        var _title = (title || "Confirm");
+        var _buttonLabels = (buttonLabels || "OK,Cancel");
+        exec(resultCallback, null, "Notification", "confirm", [message, _title, _buttonLabels]);
+    },
+
+    /**
+     * Causes the device to vibrate.
+     *
+     * @param {Integer} mills       The number of milliseconds to vibrate for.
+     */
+    vibrate: function(mills) {
+        exec(null, null, "Notification", "vibrate", [mills]);
+    },
+
+    /**
+     * Causes the device to beep.
+     * On Android, the default notification ringtone is played "count" times.
+     *
+     * @param {Integer} count       The number of beeps.
+     */
+    beep: function(count) {
+        exec(null, null, "Notification", "beep", [count]);
+    }
+};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/requestFileSystem.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/requestFileSystem.js b/lib/common/plugin/requestFileSystem.js
new file mode 100644
index 0000000..afee5d7
--- /dev/null
+++ b/lib/common/plugin/requestFileSystem.js
@@ -0,0 +1,40 @@
+var FileError = require('cordova/plugin/FileError'),
+    FileSystem = require('cordova/plugin/FileSystem'),
+    exec = require('cordova/exec');
+
+/**
+ * Request a file system in which to store application data.
+ * @param type  local file system type
+ * @param size  indicates how much storage space, in bytes, the application expects to need
+ * @param successCallback  invoked with a FileSystem object
+ * @param errorCallback  invoked if error occurs retrieving file system
+ */
+var requestFileSystem = function(type, size, successCallback, errorCallback) {
+    var fail = function(code) {
+        if (typeof errorCallback === 'function') {
+            errorCallback(new FileError(code));
+        }
+    };
+
+    if (type < 0 || type > 3) {
+        fail(FileError.SYNTAX_ERR);
+    } else {
+        // if successful, return a FileSystem object
+        var success = function(file_system) {
+            if (file_system) {
+                if (typeof successCallback === 'function') {
+                    // grab the name and root from the file system object
+                    var result = new FileSystem(file_system.name, file_system.root);
+                    successCallback(result);
+                }
+            }
+            else {
+                // no FileSystem object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+        exec(success, fail, "File", "requestFileSystem", [type, size]);
+    }
+};
+
+module.exports = requestFileSystem;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/plugin/resolveLocalFileSystemURI.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/resolveLocalFileSystemURI.js b/lib/common/plugin/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..fbf849b
--- /dev/null
+++ b/lib/common/plugin/resolveLocalFileSystemURI.js
@@ -0,0 +1,41 @@
+var DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
+    FileEntry = require('cordova/plugin/FileEntry'),
+    exec = require('cordova/exec');
+
+/**
+ * Look up file system Entry referred to by local URI.
+ * @param {DOMString} uri  URI referring to a local file or directory
+ * @param successCallback  invoked with Entry object corresponding to URI
+ * @param errorCallback    invoked if error occurs retrieving file system entry
+ */
+module.exports = function(uri, successCallback, errorCallback) {
+    // error callback
+    var fail = function(error) {
+        if (typeof errorCallback === 'function') {
+            errorCallback(new FileError(error));
+        }
+    };
+    // if successful, return either a file or directory entry
+    var success = function(entry) {
+        var result;
+
+        if (entry) {
+            if (typeof successCallback === 'function') {
+                // create appropriate Entry object
+                result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath) : new FileEntry(entry.name, entry.fullPath);
+                try {
+                    successCallback(result);
+                }
+                catch (e) {
+                    console.log('Error invoking callback: ' + e);
+                }
+            }
+        }
+        else {
+            // no Entry object returned
+            fail(FileError.NOT_FOUND_ERR);
+        }
+    };
+
+    exec(success, fail, "File", "resolveLocalFileSystemURI", [uri]);
+};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/common/utils.js
----------------------------------------------------------------------
diff --git a/lib/common/utils.js b/lib/common/utils.js
new file mode 100644
index 0000000..49f6093
--- /dev/null
+++ b/lib/common/utils.js
@@ -0,0 +1,94 @@
+function UUIDcreatePart(length) {
+    var uuidpart = "";
+    for (var i=0; i<length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length == 1) {
+            uuidchar = "0" + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+var _self = {
+    /**
+     * Does a deep clone of the object.
+     */
+    clone: function(obj) {
+        if(!obj) { 
+            return obj;
+        }
+        
+        var retVal, i;
+        
+        if(obj instanceof Array){
+            retVal = [];
+            for(i = 0; i < obj.length; ++i){
+                retVal.push(_self.clone(obj[i]));
+            }
+            return retVal;
+        }
+        
+        if (obj instanceof Function) {
+            return obj;
+        }
+        
+        if(!(obj instanceof Object)){
+            return obj;
+        }
+        
+        if(obj instanceof Date){
+            return obj;
+        }
+
+        retVal = {};
+        for(i in obj){
+            if(!(i in retVal) || retVal[i] != obj[i]) {
+                retVal[i] = _self.clone(obj[i]);
+            }
+        }
+        return retVal;
+    },
+
+    close: function(context, func, params) {
+        if (typeof params === 'undefined') {
+            return function() {
+                return func.apply(context, arguments);
+            };
+        } else {
+            return function() {
+                return func.apply(context, params);
+            };
+        }
+    },
+
+    /**
+     * Create a UUID
+     */
+    createUUID: function() {
+        return UUIDcreatePart(4) + '-' +
+            UUIDcreatePart(2) + '-' +
+            UUIDcreatePart(2) + '-' +
+            UUIDcreatePart(2) + '-' +
+            UUIDcreatePart(6);
+    },
+
+    /**
+     * Extends a child object from a parent object using classical inheritance
+     * pattern.
+     */
+    extend: (function() {
+        // proxy used to establish prototype chain
+        var F = function() {}; 
+        // extend Child from Parent
+        return function(Child, Parent) {
+            F.prototype = Parent.prototype;
+            Child.prototype = new F();
+            Child.__super__ = Parent.prototype;
+            Child.prototype.constructor = Child;
+        };
+    }())
+
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/errgen/exec.js
----------------------------------------------------------------------
diff --git a/lib/errgen/exec.js b/lib/errgen/exec.js
new file mode 100644
index 0000000..dc47fcb
--- /dev/null
+++ b/lib/errgen/exec.js
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/**
+ * 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
+ *      Asynchrounous: 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 exec(success, fail, service, action, args) {
+    var signature = service + "::" + action
+
+    //--------------------------------------------------------------------------
+    function callFail() {
+        var args = "<unable to JSONify>"
+        
+        try {
+            args = JSON.stringify(args)
+        }
+        catch (e) {}
+
+        var call = signature + "(" + args + ")"
+
+        if (!fail) {
+            console.log("failure callback not set for " + call)
+            return
+        }
+        
+        if (typeof(fail) != 'function') {
+            console.log("failure callback not a function for " + call)
+            return
+        }
+        
+        try {
+            fail("expected errgen failure for " + call)
+        }
+        catch (e) {
+            console.log("exception running failure callback for " + call)
+            console.log("   exception: " + e)
+            return
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    if (Overrides[signature]) {
+        Overrides[signature].call(null, success, fail, args)
+        return
+    }
+    
+    setTimeout(callFail, 10)
+}
+
+//------------------------------------------------------------------------------
+var Overrides = {}
+
+//------------------------------------------------------------------------------
+function addOverride(func) {
+    var name = func.name.replace('__', '::')
+    Overrides[name] = func
+}
+
+//------------------------------------------------------------------------------
+addOverride(function Accelerometer__setTimeout(success, fail, args) {
+    setTimeout(function() { 
+        fail("Accelerometer::setTimeout") 
+    }, 10)
+})
+
+//------------------------------------------------------------------------------
+addOverride(function Accelerometer__getTimeout(success, fail, args) {
+    setTimeout(function() { 
+        fail("Accelerometer::getTimeout") 
+    }, 10)
+})
+
+//------------------------------------------------------------------------------
+addOverride(function Network_Status__getConnectionInfo(success, fail) {
+    setTimeout(function() { 
+        success("none")
+    }, 10)
+})

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/errgen/platform.js
----------------------------------------------------------------------
diff --git a/lib/errgen/platform.js b/lib/errgen/platform.js
new file mode 100644
index 0000000..8677cab
--- /dev/null
+++ b/lib/errgen/platform.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+// required call to kick off the device ready callback
+require('cordova/plugin/errgen/device')
+
+//------------------------------------------------------------------------------
+module.exports = {
+    id:         "errgen",
+    initialize: function() {},
+    objects:    {}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/errgen/plugin/errgen/device.js
----------------------------------------------------------------------
diff --git a/lib/errgen/plugin/errgen/device.js b/lib/errgen/plugin/errgen/device.js
new file mode 100644
index 0000000..4e05777
--- /dev/null
+++ b/lib/errgen/plugin/errgen/device.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+
+//------------------------------------------------------------------------------
+function Device() {
+    window.DeviceInfo = {}
+    
+    this.platform  = "errgen"
+    this.version   = "any"
+    this.name      = "errgen"
+    this.phonegap  = {}
+    this.gap       = this.phonegap
+    this.uuid      = "1234-5678-9012-3456"
+    this.available = true
+    
+    require('cordova/channel').onCordovaInfoReady.fire()
+}
+
+//------------------------------------------------------------------------------
+module.exports = window.DeviceInfo = new Device()

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/android.js
----------------------------------------------------------------------
diff --git a/lib/exec/android.js b/lib/exec/android.js
deleted file mode 100644
index b3410bb..0000000
--- a/lib/exec/android.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * 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
- *      Asynchrounous: Empty string ""
- * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
- * depending upon the result of the action.
- *
- * @param {Function} success    The success callback
- * @param {Function} fail       The fail callback
- * @param {String} service      The name of the service to use
- * @param {String} action       Action to be run in cordova
- * @param {String[]} [args]     Zero or more arguments to pass to the method
- */
-var cordova = require('cordova');
-
-module.exports = function(success, fail, service, action, args) {
-  try {
-    var callbackId = service + cordova.callbackId++;
-    if (success || fail) {
-        cordova.callbacks[callbackId] = {success:success, fail:fail};
-    }
-
-    var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, action, callbackId, true]));
-
-    // If a result was returned
-    if (r.length > 0) {
-        eval("var v="+r+";");
-
-        // If status is OK, then return value back to caller
-        if (v.status === cordova.callbackStatus.OK) {
-
-            // If there is a success callback, then call it now with
-            // returned value
-            if (success) {
-                try {
-                    success(v.message);
-                } catch (e) {
-                    console.log("Error in success callback: " + callbackId  + " = " + e);
-                }
-
-                // Clear callback if not expecting any more results
-                if (!v.keepCallback) {
-                    delete cordova.callbacks[callbackId];
-                }
-            }
-            return v.message;
-        }
-
-        // If no result
-        else if (v.status === cordova.callbackStatus.NO_RESULT) {
-            // Clear callback if not expecting any more results
-            if (!v.keepCallback) {
-                delete cordova.callbacks[callbackId];
-            }
-        }
-
-        // If error, then display error
-        else {
-            console.log("Error: Status="+v.status+" Message="+v.message);
-
-            // If there is a fail callback, then call it now with returned value
-            if (fail) {
-                try {
-                    fail(v.message);
-                }
-                catch (e1) {
-                    console.log("Error in error callback: "+callbackId+" = "+e1);
-                }
-
-                // Clear callback if not expecting any more results
-                if (!v.keepCallback) {
-                    delete cordova.callbacks[callbackId];
-                }
-            }
-            return null;
-        }
-    }
-  } catch (e2) {
-    console.log("Error: "+e2);
-  }
-};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/blackberry.js
----------------------------------------------------------------------
diff --git a/lib/exec/blackberry.js b/lib/exec/blackberry.js
deleted file mode 100644
index a5fb81f..0000000
--- a/lib/exec/blackberry.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * 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
- *      Asynchrounous: Empty string ""
- * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
- * depending upon the result of the action.
- *
- * @param {Function} success    The success callback
- * @param {Function} fail       The fail callback
- * @param {String} service      The name of the service to use
- * @param {String} action       Action to be run in cordova
- * @param {String[]} [args]     Zero or more arguments to pass to the method
- */
-var blackberry = require('cordova/plugin/blackberry/manager'),
-    cordova = require('cordova');
-
-module.exports = function(success, fail, service, action, args) {
-    try {
-        var v = blackberry.exec(success, fail, service, action, args);
-
-        // If status is OK, then return value back to caller
-        if (v.status == cordova.callbackStatus.OK) {
-
-            // If there is a success callback, then call it now with returned value
-            if (success) {
-                try {
-                    success(v.message);
-                }
-                catch (e) {
-                    console.log("Error in success callback: "+ service + "." + action + " = "+e);
-                }
-
-            }
-            return v.message;
-        } else if (v.status == cordova.callbackStatus.NO_RESULT) {
-
-        } else {
-            // If error, then display error
-            console.log("Error: " + service + "." + action + " Status="+v.status+" Message="+v.message);
-
-            // If there is a fail callback, then call it now with returned value
-            if (fail) {
-                try {
-                    fail(v.message);
-                }
-                catch (e) {
-                    console.log("Error in error callback: " + service + "." + action + " = "+e);
-                }
-            }
-            return null;
-        }
-    } catch (e) {
-        alert("Error: "+e);
-    }
-};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/errgen.js
----------------------------------------------------------------------
diff --git a/lib/exec/errgen.js b/lib/exec/errgen.js
deleted file mode 100644
index dc47fcb..0000000
--- a/lib/exec/errgen.js
+++ /dev/null
@@ -1,107 +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.
- */
-
-/**
- * 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
- *      Asynchrounous: 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 exec(success, fail, service, action, args) {
-    var signature = service + "::" + action
-
-    //--------------------------------------------------------------------------
-    function callFail() {
-        var args = "<unable to JSONify>"
-        
-        try {
-            args = JSON.stringify(args)
-        }
-        catch (e) {}
-
-        var call = signature + "(" + args + ")"
-
-        if (!fail) {
-            console.log("failure callback not set for " + call)
-            return
-        }
-        
-        if (typeof(fail) != 'function') {
-            console.log("failure callback not a function for " + call)
-            return
-        }
-        
-        try {
-            fail("expected errgen failure for " + call)
-        }
-        catch (e) {
-            console.log("exception running failure callback for " + call)
-            console.log("   exception: " + e)
-            return
-        }
-    }
-
-    //--------------------------------------------------------------------------
-    if (Overrides[signature]) {
-        Overrides[signature].call(null, success, fail, args)
-        return
-    }
-    
-    setTimeout(callFail, 10)
-}
-
-//------------------------------------------------------------------------------
-var Overrides = {}
-
-//------------------------------------------------------------------------------
-function addOverride(func) {
-    var name = func.name.replace('__', '::')
-    Overrides[name] = func
-}
-
-//------------------------------------------------------------------------------
-addOverride(function Accelerometer__setTimeout(success, fail, args) {
-    setTimeout(function() { 
-        fail("Accelerometer::setTimeout") 
-    }, 10)
-})
-
-//------------------------------------------------------------------------------
-addOverride(function Accelerometer__getTimeout(success, fail, args) {
-    setTimeout(function() { 
-        fail("Accelerometer::getTimeout") 
-    }, 10)
-})
-
-//------------------------------------------------------------------------------
-addOverride(function Network_Status__getConnectionInfo(success, fail) {
-    setTimeout(function() { 
-        success("none")
-    }, 10)
-})

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/ios.js
----------------------------------------------------------------------
diff --git a/lib/exec/ios.js b/lib/exec/ios.js
deleted file mode 100644
index 32d8b6a..0000000
--- a/lib/exec/ios.js
+++ /dev/null
@@ -1,93 +0,0 @@
-    /**
-     * Creates a gap bridge iframe used to notify the native code about queued
-     * commands.
-     *
-     * @private
-     */
-var cordova = require('cordova'),
-    gapBridge,
-    createGapBridge = function() {
-        gapBridge = document.createElement("iframe");
-        gapBridge.setAttribute("style", "display:none;");
-        gapBridge.setAttribute("height","0px");
-        gapBridge.setAttribute("width","0px");
-        gapBridge.setAttribute("frameborder","0");
-        document.documentElement.appendChild(gapBridge);
-    },
-    channel = require('cordova/channel');
-
-module.exports = function() { 
-    if (!channel.onCordovaInfoReady.fired) {
-        alert("ERROR: Attempting to call cordova.exec()" +
-              " before 'deviceready'. Ignoring.");
-        return;
-    }
-
-    var successCallback, failCallback, service, action, actionArgs;
-    var callbackId = null;
-    if (typeof arguments[0] !== "string") {
-        // FORMAT ONE
-        successCallback = arguments[0];
-        failCallback = arguments[1];
-        service = arguments[2];
-        action = arguments[3];
-        actionArgs = arguments[4];
-
-        // Since we need to maintain backwards compatibility, we have to pass
-        // an invalid callbackId even if no callback was provided since plugins
-        // will be expecting it. The Cordova.exec() implementation allocates
-        // an invalid callbackId and passes it even if no callbacks were given.
-        callbackId = 'INVALID';
-    } else {
-        // FORMAT TWO
-        splitCommand = arguments[0].split(".");
-        action = splitCommand.pop();
-        service = splitCommand.join(".");
-        actionArgs = Array.prototype.splice.call(arguments, 1);
-    }
-    
-    // Start building the command object.
-    var command = {
-        className: service,
-        methodName: action,
-        arguments: []
-    };
-
-    // Register the callbacks and add the callbackId to the positional
-    // arguments if given.
-    if (successCallback || failCallback) {
-        callbackId = service + cordova.callbackId++;
-        cordova.callbacks[callbackId] = 
-            {success:successCallback, fail:failCallback};
-    }
-    if (callbackId != null) {
-        command.arguments.push(callbackId);
-    }
-
-    for (var i = 0; i < actionArgs.length; ++i) {
-        var arg = actionArgs[i];
-        if (arg == undefined || arg == null) { // nulls are pushed to the args now (becomes NSNull)
-            continue;  //command.arguments.push(arg);
-        } else if (typeof(arg) == 'object' && !(arg instanceof Array)) {
-            command.options = arg;
-        } else {
-            command.arguments.push(arg);
-        }
-    }
-
-    // Stringify and queue the command. We stringify to command now to
-    // effectively clone the command arguments in case they are mutated before
-    // the command is executed.
-    cordova.commandQueue.push(JSON.stringify(command));
-
-    // If the queue length is 1, then that means it was empty before we queued
-    // the given command, so let the native side know that we have some
-    // commands to execute, unless the queue is currently being flushed, in
-    // which case the command will be picked up without notification.
-    if (cordova.commandQueue.length == 1 && !cordova.commandQueueFlushing) {
-        if (!gapBridge) {
-            createGapBridge();
-        }
-        gapBridge.src = "gap://ready";
-    }
-};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/playbook.js
----------------------------------------------------------------------
diff --git a/lib/exec/playbook.js b/lib/exec/playbook.js
deleted file mode 100644
index ff2cbd9..0000000
--- a/lib/exec/playbook.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * 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
- *      Asynchrounous: 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) {
-    try {
-        var playbook = require('cordova/plugin/playbook/manager'),
-            cordova = require('cordova'),
-            v = playbook.exec(success, fail, service, action, args);
-
-        // If status is OK, then return value back to caller
-        if (v.status == cordova.callbackStatus.OK) {
-
-            // If there is a success callback, then call it now with returned value
-            if (success) {
-                try {
-                    success(v.message);
-                }
-                catch (e) {
-                    console.log("Error in success callback: "+cordova.callbackId+" = "+e);
-                }
-
-            }
-            return v.message;
-        } else if (v.status == cordova.callbackStatus.NO_RESULT) {
-
-        } else {
-            // If error, then display error
-            console.log("Error: Status="+v.status+" Message="+v.message);
-
-            // If there is a fail callback, then call it now with returned value
-            if (fail) {
-                try {
-                    fail(v.message);
-                }
-                catch (e) {
-                    console.log("Error in error callback: "+cordova.callbackId+" = "+e);
-                }
-            }
-            return null;
-        }
-    } catch (e) {
-        alert("Error: "+e);
-    }
-};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/test.js
----------------------------------------------------------------------
diff --git a/lib/exec/test.js b/lib/exec/test.js
deleted file mode 100644
index a5d1a69..0000000
--- a/lib/exec/test.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = jasmine.createSpy();

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/exec/wp7.js
----------------------------------------------------------------------
diff --git a/lib/exec/wp7.js b/lib/exec/wp7.js
deleted file mode 100644
index 78eef40..0000000
--- a/lib/exec/wp7.js
+++ /dev/null
@@ -1,57 +0,0 @@
-var cordova = require('cordova');
-
-/**
- * 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
- *      Asynchrounous: 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 callbackId = service + cordova.callbackId++;
-    if (typeof success == "function" || typeof fail == "function") {
-        cordova.callbacks[callbackId] = {success:success, fail:fail};
-    }
-    // generate a new command string, ex. DebugConsole/log/DebugConsole23/{"message":"wtf dude?"}
-     var command = service + "/" + action + "/" + callbackId + "/" + JSON.stringify(args);
-     // pass it on to Notify
-     window.external.Notify(command);
-};
-
-// TODO: is this what native side invokes?
-// if so pluginize under plugin/wp7
-cordovaCommandResult = function(status,callbackId,args,cast) {
-    if(status === "backbutton") {
-
-        cordova.fireEvent(document,"backbutton");
-        return "true";
-
-    } else if(status === "resume") {
-
-        cordova.onResume.fire();
-        return "true";
-
-    } else if(status === "pause") {
-
-        cordova.onPause.fire();
-        return "true";  
-    }
-    
-    var safeStatus = parseInt(status, 10);
-    if(safeStatus === cordova.callbackStatus.NO_RESULT ||
-       safeStatus === cordova.callbackStatus.OK) {
-        cordova.CallbackSuccess(callbackId,args,cast);
-    }
-    else
-    {
-        cordova.CallbackError(callbackId,args,cast);
-    }
-};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/ios/exec.js
----------------------------------------------------------------------
diff --git a/lib/ios/exec.js b/lib/ios/exec.js
new file mode 100644
index 0000000..32d8b6a
--- /dev/null
+++ b/lib/ios/exec.js
@@ -0,0 +1,93 @@
+    /**
+     * Creates a gap bridge iframe used to notify the native code about queued
+     * commands.
+     *
+     * @private
+     */
+var cordova = require('cordova'),
+    gapBridge,
+    createGapBridge = function() {
+        gapBridge = document.createElement("iframe");
+        gapBridge.setAttribute("style", "display:none;");
+        gapBridge.setAttribute("height","0px");
+        gapBridge.setAttribute("width","0px");
+        gapBridge.setAttribute("frameborder","0");
+        document.documentElement.appendChild(gapBridge);
+    },
+    channel = require('cordova/channel');
+
+module.exports = function() { 
+    if (!channel.onCordovaInfoReady.fired) {
+        alert("ERROR: Attempting to call cordova.exec()" +
+              " before 'deviceready'. Ignoring.");
+        return;
+    }
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== "string") {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        // FORMAT TWO
+        splitCommand = arguments[0].split(".");
+        action = splitCommand.pop();
+        service = splitCommand.join(".");
+        actionArgs = Array.prototype.splice.call(arguments, 1);
+    }
+    
+    // Start building the command object.
+    var command = {
+        className: service,
+        methodName: action,
+        arguments: []
+    };
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] = 
+            {success:successCallback, fail:failCallback};
+    }
+    if (callbackId != null) {
+        command.arguments.push(callbackId);
+    }
+
+    for (var i = 0; i < actionArgs.length; ++i) {
+        var arg = actionArgs[i];
+        if (arg == undefined || arg == null) { // nulls are pushed to the args now (becomes NSNull)
+            continue;  //command.arguments.push(arg);
+        } else if (typeof(arg) == 'object' && !(arg instanceof Array)) {
+            command.options = arg;
+        } else {
+            command.arguments.push(arg);
+        }
+    }
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    cordova.commandQueue.push(JSON.stringify(command));
+
+    // If the queue length is 1, then that means it was empty before we queued
+    // the given command, so let the native side know that we have some
+    // commands to execute, unless the queue is currently being flushed, in
+    // which case the command will be picked up without notification.
+    if (cordova.commandQueue.length == 1 && !cordova.commandQueueFlushing) {
+        if (!gapBridge) {
+            createGapBridge();
+        }
+        gapBridge.src = "gap://ready";
+    }
+};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/ios/platform.js
----------------------------------------------------------------------
diff --git a/lib/ios/platform.js b/lib/ios/platform.js
new file mode 100644
index 0000000..e68b52e
--- /dev/null
+++ b/lib/ios/platform.js
@@ -0,0 +1,41 @@
+module.exports = {
+    id: "ios",
+    initialize:function() {
+        // iOS doesn't allow reassigning / overriding navigator.geolocation object.
+        // So clobber its methods here instead :)
+        var geo = require('cordova/plugin/geolocation');
+        
+        navigator.geolocation.getCurrentPosition = geo.getCurrentPosition;
+        navigator.geolocation.watchPosition = geo.watchPosition;
+        navigator.geolocation.clearWatch = geo.clearWatch;
+    },
+    objects: {
+        File: { // exists natively, override
+            path: "cordova/plugin/File"
+        },
+        MediaError: { // exists natively, override
+            path: "cordova/plugin/MediaError"
+        },
+        device: {
+            path: 'cordova/plugin/ios/device'
+        },
+        console: {
+            path: 'cordova/plugin/ios/console'
+        }
+    },
+    merges:{
+        Entry:{
+            path: "cordova/plugin/ios/Entry"
+        },
+        FileReader:{
+            path: "cordova/plugin/ios/FileReader"
+        },
+        navigator:{
+            children:{
+                notification:{
+                    path:"cordova/plugin/ios/notification"
+                }
+            }
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/76f64673/lib/ios/plugin/ios/Entry.js
----------------------------------------------------------------------
diff --git a/lib/ios/plugin/ios/Entry.js b/lib/ios/plugin/ios/Entry.js
new file mode 100644
index 0000000..230da8a
--- /dev/null
+++ b/lib/ios/plugin/ios/Entry.js
@@ -0,0 +1,7 @@
+module.exports = {
+    toURL:function() {
+        // TODO: refactor path in a cross-platform way so we can eliminate 
+        // these kinds of platform-specific hacks.
+        return "file://localhost" + this.fullPath;
+    }
+}