2.5.0 (2.5.1 for npm). Uses ios, android, blackberry v2.5.0 now.
diff --git a/VERSION b/VERSION
index aa0822f..437459c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.5.0rc1
+2.5.0
diff --git a/lib/cordova-android/VERSION b/lib/cordova-android/VERSION
index aa0822f..437459c 100644
--- a/lib/cordova-android/VERSION
+++ b/lib/cordova-android/VERSION
@@ -1 +1 @@
-2.5.0rc1
+2.5.0
diff --git a/lib/cordova-android/bin/templates/cordova/appinfo.jar b/lib/cordova-android/bin/templates/cordova/appinfo.jar
index 1a088c5..fff4d0f 100644
--- a/lib/cordova-android/bin/templates/cordova/appinfo.jar
+++ b/lib/cordova-android/bin/templates/cordova/appinfo.jar
Binary files differ
diff --git a/lib/cordova-android/bin/templates/project/assets/www/index.html b/lib/cordova-android/bin/templates/project/assets/www/index.html
index bc06b24..b8c0535 100644
--- a/lib/cordova-android/bin/templates/project/assets/www/index.html
+++ b/lib/cordova-android/bin/templates/project/assets/www/index.html
@@ -33,7 +33,7 @@
                 <p class="event received">Device is Ready</p>
             </div>
         </div>
-        <script type="text/javascript" src="cordova-2.5.0rc1.js"></script>
+        <script type="text/javascript" src="cordova-2.5.0.js"></script>
         <script type="text/javascript" src="js/index.js"></script>
         <script type="text/javascript">
             app.initialize();
diff --git a/lib/cordova-android/framework/assets/js/cordova.android.js b/lib/cordova-android/framework/assets/js/cordova.android.js
index 19c9281..bfd6545 100644
--- a/lib/cordova-android/framework/assets/js/cordova.android.js
+++ b/lib/cordova-android/framework/assets/js/cordova.android.js
@@ -1,8 +1,8 @@
 // Platform: android
 
-// commit 521bbd64ed729ca76b6646d25bb01b76ee8a54b5
+// commit f50d20a87431c79a54572263729461883f611a53
 
-// File generated at :: Wed Feb 20 2013 13:49:25 GMT-0800 (PST)
+// File generated at :: Tue Feb 26 2013 13:37:51 GMT-0800 (PST)
 
 /*
  Licensed to the Apache Software Foundation (ASF) under one
@@ -1167,7 +1167,8 @@
 
 var argscheck = require('cordova/argscheck'),
     exec = require('cordova/exec'),
-    Camera = require('cordova/plugin/CameraConstants');
+    Camera = require('cordova/plugin/CameraConstants'),
+    CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle');
 
 var cameraExport = {};
 
@@ -1207,6 +1208,7 @@
                 mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions];
 
     exec(successCallback, errorCallback, "Camera", "takePicture", args);
+    return new CameraPopoverHandle();
 };
 
 cameraExport.cleanup = function(successCallback, errorCallback) {
@@ -1251,6 +1253,24 @@
 
 });
 
+// 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) {
 
diff --git a/lib/cordova-android/framework/assets/www/index.html b/lib/cordova-android/framework/assets/www/index.html
index 209e0b5..a10905d 100644
--- a/lib/cordova-android/framework/assets/www/index.html
+++ b/lib/cordova-android/framework/assets/www/index.html
@@ -19,7 +19,7 @@
 <html>
   <head>
     <title></title>
-    <script src="cordova-2.5.0rc1.js"></script>
+    <script src="cordova-2.5.0.js"></script>
   </head>
   <body>
 
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Device.java b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
index cbf49fd..5b09c13 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/Device.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
@@ -38,7 +38,7 @@
 public class Device extends CordovaPlugin {
     public static final String TAG = "Device";
 
-    public static String cordovaVersion = "2.5.0rc1";              // Cordova version
+    public static String cordovaVersion = "2.5.0";              // Cordova version
     public static String platform = "Android";                  // Device OS
     public static String uuid;                                  // Device UUID
 
diff --git a/lib/cordova-blackberry/VERSION b/lib/cordova-blackberry/VERSION
index aa0822f..437459c 100644
--- a/lib/cordova-blackberry/VERSION
+++ b/lib/cordova-blackberry/VERSION
@@ -1 +1 @@
-2.5.0rc1
+2.5.0
diff --git a/lib/cordova-blackberry/bin/templates/project/www/VERSION b/lib/cordova-blackberry/bin/templates/project/www/VERSION
index aa0822f..437459c 100644
--- a/lib/cordova-blackberry/bin/templates/project/www/VERSION
+++ b/lib/cordova-blackberry/bin/templates/project/www/VERSION
@@ -1 +1 @@
-2.5.0rc1
+2.5.0
diff --git a/lib/cordova-blackberry/bin/templates/project/www/index.html b/lib/cordova-blackberry/bin/templates/project/www/index.html
index ab0ca50..f083790 100644
--- a/lib/cordova-blackberry/bin/templates/project/www/index.html
+++ b/lib/cordova-blackberry/bin/templates/project/www/index.html
@@ -33,7 +33,7 @@
                 <p class="event received">Device is Ready</p>
             </div>
         </div>
-        <script type="text/javascript" src="cordova-2.5.0rc1.js"></script>
+        <script type="text/javascript" src="cordova-2.5.0.js"></script>
         <script type="text/javascript" src="js/index.js"></script>
         <script type="text/javascript">
             app.initialize();
diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/device/Device.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/device/Device.java
index 1e56cee..3bb4824 100644
--- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/device/Device.java
+++ b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/device/Device.java
@@ -54,7 +54,7 @@
 				JSONObject device = new JSONObject();
 				device.put( FIELD_PLATFORM, "BlackBerry");
 				device.put( FIELD_UUID, new Integer( DeviceInfo.getDeviceId()) );
-				device.put( FIELD_CORDOVA, "2.5.0rc1" );
+				device.put( FIELD_CORDOVA, "2.5.0" );
 				device.put( FIELD_MODEL, new String(DeviceInfo.getDeviceName()) );
 				device.put( FIELD_NAME, new String(DeviceInfo.getDeviceName()) );
 				device.put( FIELD_VERSION, new String(DeviceInfo.getSoftwareVersion()) );
diff --git a/lib/cordova-blackberry/javascript/cordova.blackberry.js b/lib/cordova-blackberry/javascript/cordova.blackberry.js
index cb48379..988dd43 100644
--- a/lib/cordova-blackberry/javascript/cordova.blackberry.js
+++ b/lib/cordova-blackberry/javascript/cordova.blackberry.js
@@ -1,8 +1,8 @@
 // Platform: blackberry
 
-// commit cded0ad0826489ca07ae8bdd33905a37d40f3adf
+// commit c5437f050947a65045222c6ac9fa70cf71ba334e
 
-// File generated at :: Wed Feb 20 2013 13:20:15 GMT-0800 (PST)
+// File generated at :: Wed Feb 27 2013 13:16:46 GMT-0800 (PST)
 
 /*
  Licensed to the Apache Software Foundation (ASF) under one
@@ -262,7 +262,7 @@
      */
     callbackSuccess: function(callbackId, args) {
         try {
-            cordova.callbackFromNative(callbackId, true, args.status, args.message, args.keepCallback);
+            cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
         } catch (e) {
             console.log("Error in error callback: " + callbackId + " = "+e);
         }
@@ -275,7 +275,7 @@
         // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
         // Derive success from status.
         try {
-            cordova.callbackFromNative(callbackId, false, args.status, args.message, args.keepCallback);
+            cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
         } catch (e) {
             console.log("Error in error callback: " + callbackId + " = "+e);
         }
@@ -284,13 +284,13 @@
     /**
      * Called by native code when returning the result from an action.
      */
-    callbackFromNative: function(callbackId, success, status, message, keepCallback) {
+    callbackFromNative: function(callbackId, success, status, args, keepCallback) {
         var callback = cordova.callbacks[callbackId];
         if (callback) {
             if (success && status == cordova.callbackStatus.OK) {
-                callback.success && callback.success(message);
+                callback.success && callback.success.apply(null, args);
             } else if (!success) {
-                callback.fail && callback.fail(message);
+                callback.fail && callback.fail.apply(null, args);
             }
 
             // Clear callback if not expecting any more results
@@ -724,6 +724,10 @@
 // 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.
+// This is used in conjunction with the automatic plugin JS loading CLI prototype.
+channel.createSticky('onPluginsReady');
+
 // Event to indicate that Cordova is ready
 channel.createSticky('onDeviceReady');
 
@@ -993,7 +997,8 @@
 
 var argscheck = require('cordova/argscheck'),
     exec = require('cordova/exec'),
-    Camera = require('cordova/plugin/CameraConstants');
+    Camera = require('cordova/plugin/CameraConstants'),
+    CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle');
 
 var cameraExport = {};
 
@@ -1033,6 +1038,7 @@
                 mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions];
 
     exec(successCallback, errorCallback, "Camera", "takePicture", args);
+    return new CameraPopoverHandle();
 };
 
 cameraExport.cleanup = function(successCallback, errorCallback) {
@@ -1077,6 +1083,24 @@
 
 });
 
+// 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) {
 
@@ -2500,7 +2524,7 @@
     }
 
     var fail = errorCallback && function(e) {
-        var error = new FileTransferError(e.code, e.source, e.target, e.http_status);
+        var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body);
         errorCallback(error);
     };
 
@@ -2550,7 +2574,7 @@
     };
 
     var fail = errorCallback && function(e) {
-        var error = new FileTransferError(e.code, e.source, e.target, e.http_status);
+        var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body);
         errorCallback(error);
     };
 
@@ -5184,7 +5208,7 @@
                     model: "PlayBook",
                     name: "PlayBook", // deprecated: please use device.model
                     uuid: info.uuid,
-                    cordova: "2.5.0rc1"
+                    cordova: "2.5.0"
                 });
             }),
             request = new blackberry.transport.RemoteFunctionCall("org/apache/cordova/getDeviceInfo");
@@ -6081,7 +6105,8 @@
 // file: lib/common/plugin/echo.js
 define("cordova/plugin/echo", function(require, exports, module) {
 
-var exec = require('cordova/exec');
+var exec = require('cordova/exec'),
+    utils = require('cordova/utils');
 
 /**
  * Sends the given message through exec() to the Echo plugin, which sends it back to the successCallback.
@@ -6091,11 +6116,25 @@
  * @param forceAsync  Whether to force an async return value (for testing native->js bridge).
  */
 module.exports = function(successCallback, errorCallback, message, forceAsync) {
-    var action = forceAsync ? 'echoAsync' : 'echo';
-    if (!forceAsync && message.constructor == ArrayBuffer) {
-        action = 'echoArrayBuffer';
+    var action = 'echo';
+    var messageIsMultipart = (utils.typeName(message) == "Array");
+    var args = messageIsMultipart ? message : [message];
+
+    if (utils.typeName(message) == 'ArrayBuffer') {
+        if (forceAsync) {
+            console.warn('Cannot echo ArrayBuffer with forced async, falling back to sync.');
+        }
+        action += 'ArrayBuffer';
+    } else if (messageIsMultipart) {
+        if (forceAsync) {
+            console.warn('Cannot echo MultiPart Array with forced async, falling back to sync.');
+        }
+        action += 'MultiPart';
+    } else if (forceAsync) {
+        action += 'Async';
     }
-    exec(successCallback, errorCallback, "Echo", action, [message]);
+
+    exec(successCallback, errorCallback, "Echo", action, args);
 };
 
 
@@ -9059,7 +9098,7 @@
             model: "Dev Alpha",
             name: "Dev Alpha", // deprecated: please use device.model
             uuid: blackberry.identity.uuid,
-            cordova: "2.5.0rc1"
+            cordova: "2.5.0"
         });
 
         return { "status" : cordova.callbackStatus.NO_RESULT, "message" : "Device info returned" };
@@ -9479,29 +9518,186 @@
 // file: lib/blackberry/plugin/qnx/fileTransfer.js
 define("cordova/plugin/qnx/fileTransfer", function(require, exports, module) {
 
-var cordova = require('cordova');
+var cordova = require('cordova'),
+    FileEntry = require('cordova/plugin/FileEntry'),
+    FileTransferError = require('cordova/plugin/FileTransferError'),
+    FileUploadResult = require('cordova/plugin/FileUploadResult'),
+    ProgressEvent = require('cordova/plugin/ProgressEvent'),
+    nativeResolveLocalFileSystemURI = function(uri, success, fail) {
+        if (uri.substring(0,11) !== "filesystem:") {
+            uri = "filesystem:" + uri;
+        }
+        window.webkitResolveLocalFileSystemURL(uri, success, fail);
+    },
+    xhr;
+
+function getParentPath(filePath) {
+    var pos = filePath.lastIndexOf('/');
+    return filePath.substring(0, pos + 1);
+}
+
+function getFileName(filePath) {
+    var pos = filePath.lastIndexOf('/');
+    return filePath.substring(pos + 1);
+}
+
+function cleanUpPath(filePath) {
+    var pos = filePath.lastIndexOf('/');
+    return filePath.substring(0, pos) + filePath.substring(pos + 1, filePath.length);
+}
+
+function checkURL(url) {
+    return url.indexOf(' ') === -1 ?  true : false;
+}
 
 module.exports = {
-    download: function (args, win, fail) {
-        var source = args[0],
-            target = args[1];
-
-        blackberry.io.filetransfer.download(source, target, win, fail);
+    abort: function () {
         return { "status" : cordova.callbackStatus.NO_RESULT, "message" : "async"};
     },
 
-    upload: function (args, win, fail) {
-        var path = args[0],
+    upload: function(args, win, fail) {
+        var filePath = args[0],
             server = args[1],
-            options = {
-                fileKey: args[2],
-                fileName: args[3],
-                mimeType: args[4],
-                params: args[5],
-                chunkedMode: args[6]
-            };
+            fileKey = args[2],
+            fileName = args[3],
+            mimeType = args[4],
+            params = args[5],
+            /*trustAllHosts = args[6],*/
+            chunkedMode = args[7],
+            headers = args[8];
 
-        blackberry.io.filetransfer.upload(path, server, win, fail, options);
+        if (!checkURL(server)) {
+            fail(new FileTransferError(FileTransferError.INVALID_URL_ERR));
+        }
+
+        nativeResolveLocalFileSystemURI(filePath, function(entry) {
+            entry.file(function(file) {
+                function uploadFile(blobFile) {
+                    var fd = new FormData();
+
+                    fd.append(fileKey, blobFile, fileName);
+                    for (var prop in params) {
+                        if(params.hasOwnProperty(prop)) {
+                            fd.append(prop, params[prop]);
+                        }
+                    }
+
+                    xhr = new XMLHttpRequest();
+                    xhr.open("POST", server);
+                    xhr.onload = function(evt) {
+                        if (xhr.status == 200) {
+                            var result = new FileUploadResult();
+                            result.bytesSent = file.size;
+                            result.responseCode = xhr.status;
+                            result.response = xhr.response;
+                            win(result);
+                        } else if (xhr.status == 404) {
+                            fail(new FileTransferError(FileTransferError.INVALID_URL_ERR, server, filePath, xhr.status));
+                        } else {
+                            fail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, xhr.status));
+                        }
+                    };
+                    xhr.ontimeout = function(evt) {
+                        fail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, xhr.status));
+                    };
+                    xhr.onerror = function () {
+                        fail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, this.status));
+                    };
+                    xhr.onprogress = function (evt) {
+                        win(evt);
+                    };
+
+                    for (var header in headers) {
+                        if (headers.hasOwnProperty(header)) {
+                            xhr.setRequestHeader(header, headers[header]);
+                        }
+                    }
+
+                    xhr.send(fd);
+                }
+
+                var bytesPerChunk;
+                if (chunkedMode === true) {
+                    bytesPerChunk = 1024 * 1024; // 1MB chunk sizes.
+                } else {
+                    bytesPerChunk = file.size;
+                }
+                var start = 0;
+                var end = bytesPerChunk;
+                while (start < file.size) {
+                    var chunk = file.slice(start, end, mimeType);
+                    uploadFile(chunk);
+                    start = end;
+                    end = start + bytesPerChunk;
+                }
+            }, function(error) {
+                fail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR));
+            });
+        }, function(error) {
+            fail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR));
+        });
+
+        return { "status" : cordova.callbackStatus.NO_RESULT, "message" : "async"};
+    },
+
+    download: function (args, win, fail) {
+        var source = args[0],
+            target = cleanUpPath(args[1]),
+            fileWriter;
+
+        if (!checkURL(source)) {
+            fail(new FileTransferError(FileTransferError.INVALID_URL_ERR));
+        }
+
+        xhr = new XMLHttpRequest();
+
+        function writeFile(entry) {
+            entry.createWriter(function (writer) {
+                fileWriter = writer;
+                fileWriter.onwriteend = function (evt) {
+                    if (!evt.target.error) {
+                        win(new FileEntry(entry.name, entry.toURL()));
+                    } else {
+                        fail(evt.target.error);
+                    }
+                };
+                fileWriter.onerror = function (evt) {
+                    fail(evt.target.error);
+                };
+                fileWriter.write(new Blob([xhr.response]));
+            }, function (error) {
+                fail(error);
+            });
+        }
+
+        xhr.onerror = function (e) {
+            fail(new FileTransferError(FileTransferError.CONNECTION_ERR, source, target, xhr.status));
+        };
+
+        xhr.onload = function () {
+            if (xhr.readyState === xhr.DONE) {
+                if (xhr.status === 200 && xhr.response) {
+                    nativeResolveLocalFileSystemURI(getParentPath(target), function (dir) {
+                        dir.getFile(getFileName(target), {create: true}, writeFile, function (error) {
+                            fail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR));
+                        });
+                    }, function (error) {
+                        fail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR));
+                    });
+                } else if (xhr.status === 404) {
+                    fail(new FileTransferError(FileTransferError.INVALID_URL_ERR, source, target, xhr.status));
+                } else {
+                    fail(new FileTransferError(FileTransferError.CONNECTION_ERR, source, target, xhr.status));
+                }
+            }
+        };
+        xhr.onprogress = function (evt) {
+            win(evt);
+        };
+
+        xhr.responseType = "blob";
+        xhr.open("GET", source, true);
+        xhr.send();
         return { "status" : cordova.callbackStatus.NO_RESULT, "message" : "async"};
     }
 };
@@ -10279,39 +10475,26 @@
 (function (context) {
     // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
     // We replace it so that properties that can't be clobbered can instead be overridden.
-    if (context.navigator) {
+    function replaceNavigator(origNavigator) {
         var CordovaNavigator = function() {};
-        CordovaNavigator.prototype = context.navigator;
-        context.navigator = new CordovaNavigator();
+        CordovaNavigator.prototype = origNavigator;
+        var newNavigator = new CordovaNavigator();
+        // This work-around really only applies to new APIs that are newer than Function.bind.
+        // Without it, APIs such as getGamepads() break.
+        if (CordovaNavigator.bind) {
+            for (var key in origNavigator) {
+                if (typeof origNavigator[key] == 'function') {
+                    newNavigator[key] = origNavigator[key].bind(origNavigator);
+                }
+            }
+        }
+        return newNavigator;
+    }
+    if (context.navigator) {
+        context.navigator = replaceNavigator(context.navigator);
     }
 
-    var channel = require("cordova/channel"),
-        _self = {
-            boot: function () {
-                /**
-                 * Create all cordova objects once page has fully loaded and native side is ready.
-                 */
-                channel.join(function() {
-                    var platform = require('cordova/platform');
-
-                    // Call the platform-specific initialization
-                    platform.initialize();
-
-                    // Fire event to notify that all objects are created
-                    channel.onCordovaReady.fire();
-
-                    // Fire onDeviceReady event once all constructors have run and
-                    // cordova info has been received from native side.
-                    channel.join(function() {
-                        require('cordova').fireDocumentEvent('deviceready');
-                    }, channel.deviceReadyChannelsArray);
-
-                }, [ channel.onDOMContentLoaded, channel.onNativeReady ]);
-            }
-        };
-
-    // boot up once native side is ready
-    channel.onNativeReady.subscribe(_self.boot);
+    var channel = require("cordova/channel");
 
     // _nativeReady is global variable that the native side can set
     // to signify that the native code is ready. It is a global since
@@ -10320,6 +10503,40 @@
         channel.onNativeReady.fire();
     }
 
+    /**
+     * Create all cordova objects once page has fully loaded and native side is ready.
+     */
+    var joinEvents = [ channel.onDOMContentLoaded, channel.onNativeReady ];
+
+    // If this property is set to something truthy, join on onPluginsReady too.
+    // This property is set by the automatic JS installation prototype in cordova-cli,
+    // and will be removed when the prototype either becomes mainline or is dropped.
+    if (window.__onPluginsLoadedHack) {
+        joinEvents.push(channel.onPluginsReady);
+    }
+
+    channel.join(function() {
+        var builder = require('cordova/builder'),
+            platform = require('cordova/platform');
+
+        builder.buildIntoButDoNotClobber(platform.defaults, context);
+        builder.buildIntoAndClobber(platform.clobbers, context);
+        builder.buildIntoAndMerge(platform.merges, context);
+
+        // Call the platform-specific initialization
+        platform.initialize();
+
+        // Fire event to notify that all objects are created
+        channel.onCordovaReady.fire();
+
+        // Fire onDeviceReady event once all constructors have run and
+        // cordova info has been received from native side.
+        channel.join(function() {
+            require('cordova').fireDocumentEvent('deviceready');
+        }, channel.deviceReadyChannelsArray);
+
+    }, joinEvents);
+
 }(window));
 
 // file: lib/scripts/bootstrap-blackberry.js
@@ -10335,7 +10552,7 @@
             });
         };
         wwjs.onerror = function () {
-            alert('there was a problem loading webworks.js');
+            console.error('there was a problem loading webworks.js');
         };
         document.head.appendChild(wwjs);
         break;
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
index e32da7d..204d25f 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.h
@@ -80,6 +80,7 @@
 - (void)takePicture:(CDVInvokedUrlCommand*)command;
 - (void)postImage:(UIImage*)anImage withFilename:(NSString*)filename toUrl:(NSURL*)url;
 - (void)cleanup:(CDVInvokedUrlCommand*)command;
+- (void)repositionPopover:(CDVInvokedUrlCommand*)command;
 
 - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info;
 - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
diff --git a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
index 22aca98..aabe844 100644
--- a/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
+++ b/lib/cordova-ios/CordovaLib/Classes/CDVCamera.m
@@ -93,6 +93,13 @@
         targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
     }
 
+    // If a popover is already open, close it; we only want one at a time.
+    if (([[self pickerController] popoverController] != nil) && [[[self pickerController] popoverController] isPopoverVisible]) {
+        [[[self pickerController] popoverController] dismissPopoverAnimated:YES];
+        [[[self pickerController] popoverController] setDelegate:nil];
+        [[self pickerController] setPopoverController:nil];
+    }
+
     CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
     self.pickerController = cameraPicker;
 
@@ -128,28 +135,8 @@
         if (cameraPicker.popoverController == nil) {
             cameraPicker.popoverController = [[NSClassFromString (@"UIPopoverController")alloc] initWithContentViewController:cameraPicker];
         }
-        int x = 0;
-        int y = 32;
-        int width = 320;
-        int height = 480;
-        UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
         NSDictionary* options = [command.arguments objectAtIndex:10 withDefault:nil];
-        if (options) {
-            x = [options integerValueForKey:@"x" defaultValue:0];
-            y = [options integerValueForKey:@"y" defaultValue:32];
-            width = [options integerValueForKey:@"width" defaultValue:320];
-            height = [options integerValueForKey:@"height" defaultValue:480];
-            arrowDirection = [options integerValueForKey:@"arrowDir" defaultValue:UIPopoverArrowDirectionAny];
-            if (![org_apache_cordova_validArrowDirections containsObject:[NSNumber numberWithInt:arrowDirection]]) {
-                arrowDirection = UIPopoverArrowDirectionAny;
-            }
-        }
-
-        cameraPicker.popoverController.delegate = self;
-        [cameraPicker.popoverController presentPopoverFromRect:CGRectMake(x, y, width, height)
-                                                        inView:[self.webView superview]
-                                      permittedArrowDirections:arrowDirection
-                                                      animated:YES];
+        [self displayPopover:options];
     } else {
         if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
             [self.viewController presentViewController:cameraPicker animated:YES completion:nil];
@@ -160,6 +147,39 @@
     self.hasPendingOperation = YES;
 }
 
+- (void)repositionPopover:(CDVInvokedUrlCommand*)command
+{
+    NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:nil];
+
+    [self displayPopover:options];
+}
+
+- (void)displayPopover:(NSDictionary*)options
+{
+    int x = 0;
+    int y = 32;
+    int width = 320;
+    int height = 480;
+    UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
+
+    if (options) {
+        x = [options integerValueForKey:@"x" defaultValue:0];
+        y = [options integerValueForKey:@"y" defaultValue:32];
+        width = [options integerValueForKey:@"width" defaultValue:320];
+        height = [options integerValueForKey:@"height" defaultValue:480];
+        arrowDirection = [options integerValueForKey:@"arrowDir" defaultValue:UIPopoverArrowDirectionAny];
+        if (![org_apache_cordova_validArrowDirections containsObject:[NSNumber numberWithInt:arrowDirection]]) {
+            arrowDirection = UIPopoverArrowDirectionAny;
+        }
+    }
+
+    [[[self pickerController] popoverController] setDelegate:self];
+    [[[self pickerController] popoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
+                                                                 inView:[self.webView superview]
+                                               permittedArrowDirections:arrowDirection
+                                                               animated:YES];
+}
+
 - (void)cleanup:(CDVInvokedUrlCommand*)command
 {
     // empty the tmp directory
diff --git a/lib/cordova-ios/CordovaLib/VERSION b/lib/cordova-ios/CordovaLib/VERSION
index aa0822f..437459c 100644
--- a/lib/cordova-ios/CordovaLib/VERSION
+++ b/lib/cordova-ios/CordovaLib/VERSION
@@ -1 +1 @@
-2.5.0rc1
+2.5.0
diff --git a/lib/cordova-ios/CordovaLib/cordova.ios.js b/lib/cordova-ios/CordovaLib/cordova.ios.js
index 60665b6..3d83df3 100644
--- a/lib/cordova-ios/CordovaLib/cordova.ios.js
+++ b/lib/cordova-ios/CordovaLib/cordova.ios.js
@@ -1,8 +1,8 @@
 // Platform: ios
 
-// commit 521bbd64ed729ca76b6646d25bb01b76ee8a54b5
+// commit f50d20a87431c79a54572263729461883f611a53
 
-// File generated at :: Wed Feb 20 2013 12:24:41 GMT-0800 (PST)
+// File generated at :: Tue Feb 26 2013 14:26:19 GMT-0800 (PST)
 
 /*
  Licensed to the Apache Software Foundation (ASF) under one
@@ -823,6 +823,9 @@
 }
 
 function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+       return args;
+    }
     var encodeArrayBufferAs8bitString = function(ab) {
         return String.fromCharCode.apply(null, new Uint8Array(ab));
     };
@@ -1122,7 +1125,8 @@
 
 var argscheck = require('cordova/argscheck'),
     exec = require('cordova/exec'),
-    Camera = require('cordova/plugin/CameraConstants');
+    Camera = require('cordova/plugin/CameraConstants'),
+    CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle');
 
 var cameraExport = {};
 
@@ -1162,6 +1166,7 @@
                 mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions];
 
     exec(successCallback, errorCallback, "Camera", "takePicture", args);
+    return new CameraPopoverHandle();
 };
 
 cameraExport.cleanup = function(successCallback, errorCallback) {
@@ -1206,6 +1211,25 @@
 
 });
 
+// file: lib/ios/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) {
+        var args = [ popoverOptions ];
+        exec(null, null, "Camera", "repositionPopover", args);
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
+
 // file: lib/common/plugin/CameraPopoverOptions.js
 define("cordova/plugin/CameraPopoverOptions", function(require, exports, module) {
 
diff --git a/lib/cordova-ios/RELEASENOTES.md b/lib/cordova-ios/RELEASENOTES.md
index 4ffc39b..843493e 100644
--- a/lib/cordova-ios/RELEASENOTES.md
+++ b/lib/cordova-ios/RELEASENOTES.md
@@ -18,10 +18,64 @@
 # under the License.
 #
 -->
-## Release Notes for Cordova  ##
+## Release Notes for Cordova (iOS) ##
  
  Cordova is a static library that enables developers to include the Cordova API in their iOS application projects easily, and also create new Cordova-based iOS application projects through the command-line.
 
+ ### 2.5.0 (20130301) ###
+
+* [CB-2395] Fix CDVViewController UserAgent lock
+* [CB-2207] Use a custom script for www/ copying.
+* [CB-2275] Add NSURLCache to app template.
+* [CB-2433] Deprecation notice for window.Settings
+* [CB-2276] Add whitelist method to CommandDelegate
+* [CB-2276] Remove CDVViewController from CDVLocation
+* [CB-2276] Remove CDVViewController from CDVSound
+* [CB-2276] Remove CDVViewController CDVCapture
+* [CB-1547] Ignore iframe navigations in webview delegate methods
+* [CB-1547] Take two: Ignore iframe navigations in webview delegate methods
+* [CB-2443] Add pluginInitialize method to CDVPlugin.
+* [CB-2443] Removed classSettings initializer from CDVPlugin
+* [CB-1693] Allow plugins to be loaded on start-up.
+* [CB-2276] Move Splashscreen logic out of CDVViewController
+* [CB-2389] Distinguish top-level from sub-frame navigations.
+* [CB-571] Media updates
+* [CB-2213] Added NATIVE_URI to getFileMetadata.
+* [CB-2213] Added NATIVE_URI to readAsDataURL.
+* [CB-2213] Added NATIVE_URI to getMetadata.
+* [CB-2213] Added NATIVE_URI to three methods.
+* [CB-2213] Added the AssetsLibrary framework.
+* [CB-2213] Added NATIVE_URI to copyTo and moveTo.
+* [CB-2213] Updated errors for write and truncate.
+* [CB-2213] Updated a NATIVE_URI error (getParent).
+* [CB-2213] Added NATIVE_URI to FileTransfer.upload.
+* [CB-2213] Skipped image scaling when possible.
+* [CB-2213] Added native URI request handling.
+* [CB-2411] Added camera popover repositioning.
+* [CB-2379] Update CordovaLib Project Settings according to Xcode 4.6 recommendations
+* [CB-2334] Add "body" property to FileTransferError object on iOS
+* [CB-2342] Media API allows non-whitelisted audio to be played
+* [CB-2324] iOS config.xml document should use <widget> instead of <cordova>
+* [CB-2469] Update JavaScript for iOS (2.5.0rc1)
+* CDVWebViewDelegate header was not public.
+* [CB-2516] Additional Plugin Note on Upgrading from 2.3.0 to 2.4.0
+* [CB-2510] [1/2] Updated Plugin Upgrade Guide for 2.4.0 -> 2.5.0
+* [CB-2544] Document "onload" attribute of <plugin> element in Plugin Upgrade Guide
+* [CB-2280, CB-2281] SplashScreen fade and rotation
+* Run uncrustify on CDVPlugin.m
+* Uncrustify CDVFile and CDVFileTransfer
+* Use correct MIME-type for asset-library responses.
+* Add option for ipad/iphone in cordova/emulate
+* Make CDVLocalStorage use onReset
+* Add a notification so plugins will know when page loads occur.
+* Change default value of splash screen fade to be quicker.
+* Implement useSplashScreen without using a setting
+* Don't call onReset for iframe navigation
+* function name was wrong (case sensitive)
+* Fix /bin/create script to work with GNU sed in path
+
+<br />
+
  ### 2.4.0 (20130205) ###
 
 * Make cordova_plist_to_config_xml able to handle binary plist files
diff --git a/lib/cordova-ios/guides/Cordova Plugin Upgrade Guide.md b/lib/cordova-ios/guides/Cordova Plugin Upgrade Guide.md
index bf6191b..869e4f4 100644
--- a/lib/cordova-ios/guides/Cordova Plugin Upgrade Guide.md
+++ b/lib/cordova-ios/guides/Cordova Plugin Upgrade Guide.md
@@ -20,7 +20,50 @@
 -->
 # Cordova Plugin Upgrade Guide #
 
-This document is for developers who need to upgrade their Cordova  plugins to a newer Cordova version. Starting with Cordova 1.5.0, some classes have been renamed, which will require the plugin to be upgraded. Make sure your project itself has been upgraded using the "Cordova Upgrade Guide" document.
+This document is for developers who need to upgrade their Cordova  plugins to a newer Cordova version. Starting with Cordova 1.5.0, some classes have been renamed, which will require the plugin to be upgraded. Make sure your project itself has been upgraded using the [Cordova iOS Upgrading Guide](http://cordova.apache.org/docs/en/edge/guide_upgrading_ios_index.md.html#Upgrading%20Cordova%20iOS) document.
+
+## Upgrading older Cordova plugins to 2.5.0 ##
+
+1. **Install** Cordova 2.5.0
+2. Follow the **"Upgrading older Cordova plugins to 2.4.0"** section, if necessary
+3. All plugins are able to be loaded at startup now, through the "onload" attribute of the **&lt;plugin&gt;** element, for example:
+
+        <plugin name="MyPlugin" value="MyPluginClass" onload="true" />
+
+   All plugins should be able to be run at startup successfully even if they are not designed to (since config.xml allows it), and a plugin's startup should not take too much time to load in its initWithWebView and pluginInitialize functions since the loading of plugins at startup is a synchronous process. **Loading of numerous plugins at startup (especially if they cumulatively take too long) might affect your startup time detrimentally.**
+    
+4. Note the changes in the **CDVPlugin** class in the section below
+
+### Changes in the CDVPlugin class ###
+
+**REMOVED:**
+
+    - (CDVPlugin*)initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings;
+
+**ADDED:**
+
+    - (void)pluginInitialize;
+
+Thus, a plugin will be initialized in a two-step process:
+
+    - (CDVPlugin*)initWithWebView:(UIWebView*)theWebView;
+    - (void)pluginInitialize;
+
+**ADDED:** 
+
+A plugin can listen for the **"CDVPageDidLoadNotification"** NSNotification, which is sent whenever a new web-page has finished loading in the CordovaWebView. The **"CDVPageDidLoadNotification""** NSNotification is passed the CordovaWebView, which is set as the **object** property of the NSNotification.
+
+**CHANGED:** 
+
+The **"CDVPluginResetNotification""** NSNotification is now passed the CordovaWebView, which is set as the **object** property of the NSNotification. A plugin can receive this notification when it overrides the CDVPlugin **onReset** selector:
+    
+    - (void) onReset:(NSNotification*)notification;
+
+**ADDED:** 
+
+The plugin's **commandDelegate** property has a new **settings** property that represents the application's settings (preferences from the config.xml file). e.g.
+
+    NSString* mySetting = self.commandDelegate.settings[@"MySetting"];
 
 ## Upgrading older Cordova plugins to 2.4.0 ##
 
@@ -29,6 +72,19 @@
 
 JSONKit usage has been removed, and replaced by AppKit's NSJSONSerialization. If you are using CordovaLib's JSONKit, either use your own JSONKit or use NSJSONSerialization instead.
 
+Because of NSJSONSerialization use in Cordova 2.4.0, all the objects in a CDVInvokedUrlCommand.arguments NSArray are immutable. Here is a mutable example: e.g.
+	 
+	 // command is a CDVInvokedUrlCommand object. Here we create a mutable copy of the object
+    NSMutableDictionary* dict = [[command.arguments objectAtIndex:0] mutableCopy];
+    
+    // do things with the dict object, then at the end release it if non-ARC
+    #if __has_feature(objc_arc)
+        // do nothing for ARC
+    #else
+    	 // release it if non-ARC
+    	 [dict release];
+    #endif
+    
 
 ## Upgrading older Cordova plugins to 2.3.0 ##
 
diff --git a/package.json b/package.json
index 82e4e2e..ac0bedc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "cordova",
-  "version": "2.5.0",
+  "version": "2.5.1",
   "preferGlobal": "true",
   "description": "Cordova command line interface tool",
   "main": "cordova",