You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/05/24 01:41:34 UTC

[13/38] updated android, ios, bb libraries to 2.8.x branch. fixed a few assertions with project changes. removed blackberry support until create script can be finalized.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/event.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/event.js b/lib/cordova-blackberry/framework/lib/event.js
new file mode 100644
index 0000000..880e6c4
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/event.js
@@ -0,0 +1,84 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _handlers = {},
+    _webview = require("./webview");
+
+module.exports = {
+    trigger: function (actionEvent) {
+        var args = Array.prototype.slice.call(arguments),
+            executeString = "webworks.event.trigger('" + actionEvent + "', '" + escape(encodeURIComponent(JSON.stringify(args.slice(1)))) + "')";
+
+        if (_handlers.hasOwnProperty(actionEvent)) {
+            _handlers[actionEvent].forEach(function (webview) {
+                webview.executeJavaScript(executeString);
+            });
+        } else {
+            //Just dump it in the content webview for consistency
+            _webview.executeJavascript(executeString);
+        }
+    },
+
+    add: function (action, webview) {
+        var triggerEvent;
+
+        if (action) {
+            //Use action.event for old extensions that may not have triggerEvent defined
+            triggerEvent = action.triggerEvent || action.event;
+
+            if (!action.once) {
+                action.context.addEventListener(action.event, action.trigger || this.trigger);
+            }
+
+            //If there are no registered listeners for this event, create an array to hold them
+            if (!_handlers.hasOwnProperty(triggerEvent)) {
+                _handlers[triggerEvent] = [];
+            }
+            //If the webview is not in the list of webviews listening to this action then add it
+            if (!_handlers[triggerEvent].some(function (handlerWebView) {
+                    return handlerWebView.id === webview.id;
+                })) {
+                _handlers[triggerEvent].push(webview);
+            }
+
+        } else {
+            throw "Action is null or undefined";
+        }
+    },
+
+    remove: function (action, webview) {
+        if (action) {
+            action.context.removeEventListener(action.event, action.trigger || this.trigger);
+
+            //Remove the webview from the _handlers
+            if (_handlers.hasOwnProperty(action.event)) {
+
+                _handlers[action.event] = _handlers[action.event].filter(function (sourceWebview) {
+                    return sourceWebview.id !== webview.id;
+                });
+
+                //If the array is empty delete it
+                if (_handlers[action.event].length === 0) {
+                    delete _handlers[action.event];
+                }
+            }
+
+        } else {
+            throw "Action is null or undefined";
+        }
+
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/events/applicationEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/events/applicationEvents.js b/lib/cordova-blackberry/framework/lib/events/applicationEvents.js
new file mode 100644
index 0000000..14a8f9e
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/events/applicationEvents.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module.exports = {
+    addEventListener: function (event, trigger) {
+        if (event) {
+            event = "application." + event;
+            window.qnx.webplatform.getApplication().addEventListener(event, trigger);
+        } else {
+            console.warn("Attempting to register for 'falsey' event: " + event);
+        }
+    },
+    removeEventListener: function (event, trigger) {
+        if (event) {
+            event = "application." + event;
+            window.qnx.webplatform.getApplication().removeEventListener(event, trigger);
+        } else {
+            console.warn("Attempting to un-register for 'falsey' event: " + event);
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/events/deviceEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/events/deviceEvents.js b/lib/cordova-blackberry/framework/lib/events/deviceEvents.js
new file mode 100644
index 0000000..939357b
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/events/deviceEvents.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module.exports = {
+    addEventListener: function (event, trigger) {
+        if (event) {
+            event = "device." + event;
+            window.qnx.webplatform.device.addEventListener(event, trigger);
+        } else {
+            console.warn("Attempting to register for 'falsey' event: " + event);
+        }
+    },
+    removeEventListener: function (event, trigger) {
+        if (event) {
+            event = "device." + event;
+            window.qnx.webplatform.device.removeEventListener(event, trigger);
+        } else {
+            console.warn("Attempting to un-register for 'falsey' event: " + event);
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/exception.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/exception.js b/lib/cordova-blackberry/framework/lib/exception.js
new file mode 100644
index 0000000..f0a8467
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/exception.js
@@ -0,0 +1,69 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module.exports = {
+
+    types: {
+        Application: "Application",
+        ArgumentLength: "ArgumentLength",
+        ArgumentType: "ArgumentType",
+        Argument: "Argument",
+        NotificationType: "NotificationType",
+        NotificationStateType: "NotificationStateType",
+        DomObjectNotFound: "DomObjectNotFound",
+        MethodNotImplemented: "MethodNotImplemented",
+        InvalidState: "InvalidState",
+        ApplicationState: "ApplicationState"
+    },
+
+    handle: function handle(exception, reThrow) {
+        reThrow = reThrow || false;
+
+        var eMsg = exception.message || "exception caught!",
+        msg = eMsg + "\n\n" + (exception.stack || "*no stack provided*") + "\n\n";
+
+        console.error(msg);
+
+        if (reThrow) {
+            throw exception;
+        }
+    },
+
+    raise: function raise(exceptionType, message, customExceptionObject) {
+        var obj = customExceptionObject || {
+                type: "",
+                message: "",
+
+                toString: function () {
+                    var result = this.name + ': "' + this.message + '"';
+
+                    if (this.stack) {
+                        result += "\n" + this.stack;
+                    }
+                    return result;
+                }
+            };
+
+        message = message || "";
+
+        obj.name = exceptionType;
+        obj.type = exceptionType;
+        // TODO: include the exception objects original message if exists
+        obj.message = message;
+
+        throw obj;
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/framework.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/framework.js b/lib/cordova-blackberry/framework/lib/framework.js
new file mode 100644
index 0000000..5de045c
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/framework.js
@@ -0,0 +1,172 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var utils = require('./utils'),
+    controllerWebView = require('./controllerWebView'),
+    webview = require('./webview'),
+    overlayWebView = require('./overlayWebView'),
+    config = require("./config"),
+    appEvents = require("./events/applicationEvents"),
+    actionMap = {
+        pause: {
+            event: "inactive",
+            trigger: function () {
+                webview.executeJavascript("cordova.fireDocumentEvent('pause')");
+            }
+        },
+        resume: {
+            event: "active",
+            trigger: function () {
+                webview.executeJavascript("cordova.fireDocumentEvent('resume')");
+            }
+        }
+    };
+
+function addEvents() {
+    for (var action in actionMap) {
+        if (actionMap.hasOwnProperty(action)) {
+            appEvents.addEventListener(actionMap[action].event, actionMap[action].trigger);
+        }
+    }
+}
+
+function removeEvents() {
+    for (var action in actionMap) {
+        if (actionMap.hasOwnProperty(action)) {
+            appEvents.removeEventListener(actionMap[action].event, actionMap[action].trigger);
+        }
+    }
+}
+
+function showWebInspectorInfo() {
+    var port = window.qnx.webplatform.getApplication().webInspectorPort,
+        messageObj = {};
+
+    qnx.webplatform.device.getNetworkInterfaces(function (networkInfo) {
+        var connectedInterface;
+
+        utils.forEach(networkInfo, function (info) {
+            if (info && !connectedInterface) {
+                connectedInterface = info;
+            }
+        }, this);
+
+        messageObj.title = "Web Inspector Enabled";
+        if (connectedInterface) {
+            messageObj.htmlmessage =  "\n ip4:    " + connectedInterface.ipv4Address + ":" + port + "<br/> ip6:    " + connectedInterface.ipv6Address + ":" + port;
+        } else {
+            messageObj.message = "";
+        }
+        messageObj.dialogType = 'JavaScriptAlert';
+        overlayWebView.showDialog(messageObj);
+    });
+}
+
+var _self = {
+    start: function (url) {
+        var callback,
+            showUrlCallback;
+
+        // Set up the controller WebView
+        controllerWebView.init(config);
+
+        webview.create(function () {
+            if (config.enableFlash) {
+                //Set webview plugin directory [required for flash]
+                webview.setExtraPluginDirectory('/usr/lib/browser/plugins');
+
+                //Enable plugins for the webview [required for flash]
+                webview.setEnablePlugins(true);
+
+                //Enable flash for the childWebViews
+                controllerWebView.onChildWebViewCreated = function (child) {
+                    //Set webview plugin directory [required for flash]
+                    child.setExtraPluginDirectory('/usr/lib/browser/plugins');
+
+                    //Enable plugins for the webview [required for flash]
+                    child.pluginsEnabled = true;
+                };
+            }
+
+            if (!config.enableWebSecurity) {
+                webview.enableCrossSiteXHR = true;
+            }
+
+            if (!config.enablePopupBlocker) {
+                qnx.webplatform.nativeCall('webview.setBlockPopups', webview.id, false);
+            }
+            // Workaround for executeJavascript doing nothing for the first time
+
+            webview.executeJavascript("1 + 1");
+
+            url = url || config.content;
+
+            showUrlCallback = function () {
+                overlayWebView.removeEventListener("DocumentLoadFinished", showUrlCallback);
+                showUrlCallback = null;
+
+                // Start page
+                if (url) {
+                    webview.setURL(url);
+                }
+            };
+
+            overlayWebView.create(function () {
+                overlayWebView.addEventListener("DocumentLoadFinished", showUrlCallback);
+
+                overlayWebView.setURL("local:///chrome/ui.html");
+                overlayWebView.renderContextMenuFor(webview);
+                overlayWebView.handleDialogFor(webview);
+                controllerWebView.dispatchEvent('ui.init', null);
+                webview.setUIWebViewObj(overlayWebView.getWebViewObj());
+                if (config.enableChildWebView) {
+                    overlayWebView.bindAppWebViewToChildWebViewControls(webview);
+                } else {
+                    webview.onChildWindowOpen = function (data) {
+                        var parsedData = JSON.parse(data);
+                        utils.invokeInBrowser(parsedData.url);
+                    };
+                }
+                if (config.enableFormControl) {
+                    overlayWebView.getWebViewObj().formcontrol.subscribeTo(webview);
+                }
+            });
+        },
+        {
+            debugEnabled : config.debugEnabled
+        });
+
+        addEvents();
+
+        //if debugging is enabled, show the IP and port for webinspector
+        if (config.debugEnabled) {
+            callback = function () {
+                showWebInspectorInfo();
+
+                //Remove listener. Alert should only be shown once.
+                webview.removeEventListener("DocumentLoadFinished", callback);
+            };
+
+            webview.addEventListener("DocumentLoadFinished", callback);
+        }
+    },
+    stop: function () {
+        removeEvents();
+        webview.destroy();
+    }
+};
+
+module.exports = _self;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/jnext.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/jnext.js b/lib/cordova-blackberry/framework/lib/jnext.js
new file mode 100755
index 0000000..d0e4d79
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/jnext.js
@@ -0,0 +1,185 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*global objJSExt */
+
+function JNEXT_() {
+    var self = this;
+    var m_bFirstRequire = true;
+
+    self.m_arEvents = {};
+
+    self.onPageLoad = function() {
+    };
+
+    self.attachToDOM = function() {
+        // Make sure JNEXT onPageLoad is called when page load
+        //  completes without damaging existing onLoad handlers
+        var prevOnLoad = window.onload;
+        if( typeof window.onload != 'function') {
+            window.onload = self.onPageLoad;
+        } else {
+            window.onload = function() {
+                if(prevOnLoad) {
+                    prevOnLoad();
+                }
+
+                self.onPageLoad();
+            };
+        }
+
+        // Unobtrusively add the JNEXT plugin or ActiveX to the DOM
+        var objBody = document.getElementsByTagName("body")[0];
+        var objDiv = document.createElement('div');
+        var strHTML;
+
+        if(window.ActiveXObject) {
+            strHTML = '<object id="objJSExt" width="0" height="0" classid="CLSID:C802F39D-BF85-427a-A334-77E501DB62E9" codebase="jnext.ocx"></object>';
+            strHTML += '<script language="JavaScript" for="objJSExt" EVENT="Js2nEvent( strEvent )">JNEXT.processEvent(strEvent)</script>';
+        } else {
+            var strAddSrc = "";
+            if(navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Windows") != -1) {
+                // This hack required on Safari for Windows
+                strAddSrc = 'src="./jnext/safari.foo"';
+            }
+            strHTML = '<embed id="objJSExt" ' + strAddSrc + ' type="application/jnext-scriptable-plugin" width="0" height="0">';
+        }
+
+        objDiv.innerHTML = strHTML;
+        objBody.appendChild(objDiv);
+    };
+
+    self.getosname = function() {
+        return objJSExt.sendCmd("osname");
+    };
+
+    self.require = function(strLibrary) {
+        // Load a required JNEXT plugin
+        var strCmd;
+        var strVal;
+        var arParams;
+
+        if(m_bFirstRequire) {
+            strCmd = "userAgent " + navigator.userAgent;
+            strVal = objJSExt.sendCmd(strCmd);
+            arParams = strVal.split(" ");
+            if(arParams[0] != "Ok") {
+                alert("userAgent " + strVal);
+                return false;
+            }
+            self.m_bFirstRequire = false;
+        }
+        strCmd = "Require " + strLibrary;
+        strVal = objJSExt.sendCmd(strCmd);
+        arParams = strVal.split(" ");
+        if(arParams[0] != "Ok") {
+            alert("Require " + strVal);
+            return false;
+        }
+
+        return true;
+    };
+
+    self.createObject = function(strObjName) {
+        // Create an instance of a native object
+        var strCmd;
+        var strVal;
+        var arParams;
+        strVal = objJSExt.sendCmd("CreateObject " + strObjName);
+        arParams = strVal.split(" ");
+        if(arParams[0] != "Ok") {
+            alert("CreateObject: " + strVal);
+            return "";
+        }
+        return arParams[1];
+    };
+
+    self.invoke = function(strObjId, strMethod, strParams) {
+        // Invoke a method of a given instance of a native object
+        var strCmd = "InvokeMethod " + strObjId + " " + strMethod;
+
+        if( typeof (strParams) != "undefined") {
+            strCmd += " " + strParams;
+        }
+
+        return objJSExt.sendCmd(strCmd);
+    };
+
+    self.registerEvents = function(objNotify) {
+        var strId = objNotify.getId();
+        self.m_arEvents[strId] = objNotify;
+    };
+
+    self.unregisterEvents = function(objNotify) {
+        var strId = objNotify.getId();
+        delete self.m_arEvents[strId];
+    };
+
+    self.processEvent = function(strNativeEvt) {
+        // Process an event received from native code. The event
+        // containes the target JavaScript object id and the
+        // relevant parameters.
+
+        var arParams = strNativeEvt.split(" ");
+        var strObjId = arParams[0];
+        var strEvent = strNativeEvt.substring(strObjId.length + 1);
+
+        var objNotify = self.m_arEvents[strObjId];
+        if( typeof (objNotify) == 'undefined') {
+            alert("Warning: No object with Id " + strId + " found for event " + strEvent);
+            return;
+        }
+
+        // This will now be handled by the appropriate JavaScript
+        // JNEXT extension object
+        objNotify.onEvent(strEvent);
+    };
+
+    self.ajaxGet = function(strUrl, id) {
+        var req = false;
+        if(window.ActiveXObject) {
+            try {
+                req = new ActiveXObject("Msxml2.XMLHTTP");
+            } catch (e) {
+                try {
+                    req = new ActiveXObject("Microsoft.XMLHTTP");
+                } catch (ex) {
+                }
+            }
+        } else if(window.XMLHttpRequest) {
+            req = new XMLHttpRequest();
+        } else {
+            return false;
+        }
+
+        req.onreadystatechange = function() {
+            if(req.readyState == 4 && (req.status == 200 || window.location.href.indexOf("http") == -1)) {
+                self.onAjaxRecv(req.responseText);
+            }
+        };
+
+        req.open('GET', strUrl, true);
+        req.send(null);
+    };
+
+    self.onAjaxRecv = function(strContent) {
+        alert(strContent);
+    };
+
+    self.attachToDOM();
+}
+
+window.JNEXT = new JNEXT_();
+module.exports = JNEXT;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/overlayWebView.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/overlayWebView.js b/lib/cordova-blackberry/framework/lib/overlayWebView.js
new file mode 100644
index 0000000..a2bba69
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/overlayWebView.js
@@ -0,0 +1,143 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var CHROME_HEIGHT = 0,
+    webview,
+    _webviewObj;
+
+webview =
+    {
+
+    create: function (ready, configSettings) {
+        _webviewObj = window.qnx.webplatform.createUIWebView(function () {
+
+            _webviewObj.visible = true;
+            _webviewObj.active = true;
+            _webviewObj.zOrder = 2;
+            _webviewObj.enableCrossSiteXHR = true;
+            _webviewObj.setGeometry(0, 0, screen.width, screen.height);
+            _webviewObj.addEventListener("DocumentLoadFinished", function () {
+                _webviewObj.default.setDefaultFont();
+                _webviewObj.visible = true;
+            });
+
+            _webviewObj.allowRpc = true;
+            _webviewObj.backgroundColor = 0x00FFFFFF;
+            _webviewObj.sensitivity = "SensitivityTest";
+            _webviewObj.devicePixelRatio = 1;
+            _webviewObj.allowQnxObject = true;
+
+            if (ready && typeof ready === 'function') {
+                ready();
+            }
+
+            window.qnx.webplatform.getController().dispatchEvent("overlayWebView.initialized", [_webviewObj]);
+
+        });
+    },
+
+    destroy: function () {
+        _webviewObj.destroy();
+    },
+
+    setURL: function (url) {
+        _webviewObj.url = url;
+    },
+
+    setGeometry: function (x, y, width, height) {
+        _webviewObj.setGeometry(x, y, width, height);
+    },
+
+    setSensitivity : function (sensitivity) {
+        _webviewObj.sensitivity = sensitivity;
+    },
+
+    setApplicationOrientation: function (angle) {
+        _webviewObj.setApplicationOrientation(angle);
+    },
+
+    notifyApplicationOrientationDone: function () {
+        _webviewObj.notifyApplicationOrientationDone();
+    },
+
+    executeJavascript: function (js) {
+        _webviewObj.executeJavaScript(js);
+    },
+
+    windowGroup: function () {
+        return _webviewObj.windowGroup;
+    },
+
+    notifyContextMenuCancelled: function () {
+        _webviewObj.notifyContextMenuCancelled();
+    },
+
+    bindAppWebViewToChildWebViewControls: function (appWebView) {
+        if (_webviewObj && _webviewObj.childwebviewcontrols) {
+            _webviewObj.childwebviewcontrols.subscribeTo(appWebView);
+        }
+    },
+
+    renderContextMenuFor: function (targetWebView) {
+        return _webviewObj.contextMenu.subscribeTo(targetWebView);
+    },
+
+    handleDialogFor: function (targetWebView) {
+        return _webviewObj.dialog.subscribeTo(targetWebView);
+    },
+
+    showDialog: function (description, callback) {
+        return _webviewObj.dialog.show(description, callback);
+    },
+
+    getWebViewObj: function (webview) {
+        return _webviewObj;
+    },
+
+    addEventListener: function (eventName, callback) {
+        _webviewObj.addEventListener(eventName, callback);
+    },
+
+    removeEventListener: function (eventName, callback) {
+        _webviewObj.removeEventListener(eventName, callback);
+    },
+
+    showToast : function (message, options) {
+        return _webviewObj.toast.show(message, options);
+    },
+
+    showInvocationList: function (request, title, success, error) {
+        _webviewObj.invocationlist.show(request, title, success, error);
+    }
+};
+
+webview.__defineGetter__('id', function () {
+    if (_webviewObj) {
+        return _webviewObj.id;
+    }
+});
+
+webview.__defineGetter__('zOrder', function () {
+    return _webviewObj.zOrder;
+});
+
+webview.__defineGetter__('contextMenu', function () {
+    if (_webviewObj) {
+        return _webviewObj.contextMenu;
+    }
+});
+
+module.exports = webview;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/plugins/default.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/plugins/default.js b/lib/cordova-blackberry/framework/lib/plugins/default.js
new file mode 100644
index 0000000..8347917
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/plugins/default.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010-2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Whitelist = require("../policy/whitelist").Whitelist,
+    whitelist = new Whitelist();
+
+module.exports = {
+
+    exec: function (request, succ, fail, args, env) {
+        var extPath = "plugin/" + request.params.ext + "/index",
+            requestObj = {
+                extension: null,
+                method: null,
+                getExtension: function () {
+                    if (frameworkModules.indexOf(extPath + ".js") !== -1) {
+                        this.extension = require("../utils").loadModule("../" + extPath);
+                        return requestObj;
+                    } else {
+                        throw {code: 404, msg: "Extension " + request.params.ext + " not found"};
+                    }
+                },
+                getMethod: function () {
+                    var methodParts = request.params.method ? request.params.method.split('/') : [request.params.method],
+                        extMethod;
+
+                    try {
+                        extMethod = this.extension[methodParts.shift()];
+                        extMethod = methodParts.reduce(function (previous, current) {
+                            if (previous[current]) {
+                                return previous[current];
+                            } else {
+                                throw {code: 404, msg: "Method " + request.params.method + " for " + request.params.ext + " not found"};
+                            }
+                        }, extMethod);
+
+                        if (extMethod && typeof extMethod === "function") {
+                            this.method = extMethod;
+                            return requestObj;
+                        } else {
+                            throw {code: 404, msg: "Method " + request.params.method + " for " + request.params.ext + " not found"};
+                        }
+                    } catch (e) {
+                        throw {code: 404, msg: "Method " + request.params.method + " for " + request.params.ext + " not found"};
+                    }
+                },
+                exec: function () {
+                    this.method(succ, fail, args, env);
+                }
+            };
+
+        try {
+            requestObj.getExtension().getMethod().exec();
+        } catch (e) {
+            console.warn(e.msg);
+            fail(-1, e.msg, e.code);
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/plugins/event.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/plugins/event.js b/lib/cordova-blackberry/framework/lib/plugins/event.js
new file mode 100644
index 0000000..441bc70
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/plugins/event.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _event = require("../../lib/event"),
+    ONCE_EVENT_ERROR = "Error occured while adding once event listener.",
+    ERROR_ID = -1;
+
+module.exports = {
+    once: function (request, success, fail, args, env) {
+        try {
+            var eventName = decodeURIComponent(args.eventName).replace(/\"/g, ""),
+                action = {
+                    once: true,
+                    event: eventName
+                };
+
+            _event.add(action, env.webview);
+
+            if (success) {
+                success();
+            }
+        }
+        catch (e) {
+            if (fail) {
+                fail(ERROR_ID, ONCE_EVENT_ERROR);
+            }
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/policy/folderAccess.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/policy/folderAccess.js b/lib/cordova-blackberry/framework/lib/policy/folderAccess.js
new file mode 100644
index 0000000..5cd5690
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/policy/folderAccess.js
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var util = require("../utils");
+
+// Removes the start and end slashes from the path
+function _trimSurroundingSlashes(path) {
+    // Trim starting slash
+    if (util.startsWith(path, "/")) {
+        path = path.substr(1);
+    }
+
+    // Trim ending slash
+    if (util.endsWith(path, "/")) {
+        path = path.substr(0, path.length - 1);
+    }
+
+    return path;
+}
+
+// Determines the depth of the given path
+// Folder path must not include the scheme or the host
+function _determineDepth(folderPath) {
+    var depthCount = 0;
+
+    // Replace all backslashes with forward slash
+    folderPath = folderPath.replace("\\", "/");
+
+    // Special case: "/" is the given path
+    if (folderPath === "/") {
+        return 0;
+    }
+
+    folderPath = _trimSurroundingSlashes(folderPath);
+
+    // Count slashes remaining
+    while (folderPath.indexOf("/") !== -1) {
+        depthCount = depthCount + 1;
+
+        // Add 1 to skip the slash
+        folderPath = folderPath.substring(folderPath.indexOf("/") + 1);
+    }
+
+    // Add one more for the remaining folder
+    depthCount += 1;
+
+    return depthCount;
+}
+
+// Parse a folder path up to the desired depth
+function _getPath(folderPath, desiredDepth) {
+    var depthCount = 0, builtPath = "";
+
+    // Special case: Desired depth is 0
+    if (desiredDepth === 0) {
+        return "/";
+    }
+
+    // Replace all backslashes with forward slash
+    folderPath = folderPath.replace("\\", "/");
+
+    folderPath = _trimSurroundingSlashes(folderPath);
+
+    // Count slashes remaining
+    while (depthCount < desiredDepth) {
+        depthCount += 1;
+
+        // Add 1 to skip the slash
+        builtPath += "/" + folderPath.substring(0, folderPath.indexOf('/'));
+        folderPath = folderPath.substring(folderPath.indexOf('/') + 1);
+    }
+
+    return builtPath;
+}
+
+function WebFolderAccessManager() {
+    this._pathCollection = {};
+    this._maxPathLength = 0;
+}
+
+WebFolderAccessManager.prototype.addAccess = function (folderPath, access) {
+    if (!folderPath) {
+        folderPath = "/";
+    }
+
+    // Trim surrounding slashes for consistency
+    // The root "/" is a special case that does not need this trimming
+    if (folderPath !== "/") {
+        folderPath = "/" + _trimSurroundingSlashes(folderPath);
+    }
+
+    folderPath = folderPath.toLowerCase();
+
+    this._pathCollection[folderPath] = access;
+
+    // Determine the depth of the path
+    this._maxPathLength = Math.max(this._maxPathLength, _determineDepth(folderPath));
+};
+
+WebFolderAccessManager.prototype.getAccess = function (folderPath) {
+    var depth = _determineDepth(folderPath);
+    return this.getAccessRecursively(folderPath, depth);
+};
+
+WebFolderAccessManager.prototype.fetchAccess = function (folderPath) {
+    var queryIndex, folderPathWildcard;
+
+    if (!this._pathCollection.hasOwnProperty(folderPath)) {
+        // If there isn't an exact match and folderPath contains query string,
+        // check if the path collection contains an access with the same folderPath
+        // but with wildcard query
+        if ((queryIndex = folderPath.indexOf("?")) > -1) {
+            folderPathWildcard = folderPath.slice(0, queryIndex + 1) + "*";
+
+            if (this._pathCollection.hasOwnProperty(folderPathWildcard)) {
+                return this._pathCollection[folderPathWildcard];
+            }
+        }
+
+        return null;
+    } else {
+        return this._pathCollection[folderPath];
+    }
+};
+
+WebFolderAccessManager.prototype.getAccessRecursively = function (folderPath, pathLength) {
+    var fetchedAccess,
+        newPathLength,
+        newPath;
+
+    if (!folderPath) {
+        return null;
+    }
+
+    folderPath = folderPath.toLowerCase();
+
+    if (!!(fetchedAccess = this.fetchAccess(folderPath))) {
+        return fetchedAccess;
+    } else {
+        // Truncate the end portion of the path and try again
+        newPathLength = Math.min(this._maxPathLength, pathLength - 1);
+        newPath = _getPath(folderPath, newPathLength);
+
+        return this.getAccessRecursively(newPath, newPathLength);
+    }
+};
+
+function WebFolderAccess() {
+    this._mgr = new WebFolderAccessManager();
+}
+
+// folderPath - folder path must not include the scheme or the host
+WebFolderAccess.prototype.addAccess = function (folderPath, access) {
+    this._mgr.addAccess(folderPath, access);
+};
+
+// folderPath - folder path must not include the scheme or the host
+WebFolderAccess.prototype.getAccess = function (folderPath) {
+    return this._mgr.getAccess(folderPath);
+};
+
+exports.WebFolderAccess = WebFolderAccess;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/policy/webkitOriginAccess.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/policy/webkitOriginAccess.js b/lib/cordova-blackberry/framework/lib/policy/webkitOriginAccess.js
new file mode 100644
index 0000000..84adb49
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/policy/webkitOriginAccess.js
@@ -0,0 +1,123 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var config = require('./../config'),
+    utils = require('./../utils'),
+    Whitelist = require('./whitelist').Whitelist,
+    LOCAL_URI = "local://",
+    FILE_URI = "file://",
+    WW_URI = utils.getURIPrefix(),
+    _domains = [
+        {
+            url: LOCAL_URI,
+            allowSubDomains: true
+        }
+    ],
+    _webviews = [],
+    _isInitialized = false,
+    _whitelist = new Whitelist();
+
+function addOriginAccessWhitelistEntry(webview, source, destination, allowSubDomains) {
+    webview.addOriginAccessWhitelistEntry(source, destination, !!allowSubDomains);
+}
+
+function addDomain(url, allowSubDomains) {
+    var parsedUri = utils.parseUri(url);
+
+    allowSubDomains = !!allowSubDomains;
+
+    if (utils.isLocalURI(parsedUri)) {
+        url = LOCAL_URI;
+    } else if (utils.isFileURI(parsedUri)) {
+        url = FILE_URI;
+    } else {
+        url = parsedUri.source;
+    }
+
+    if (_whitelist.isAccessAllowed(url) && !_domains.some(function (domain) {
+        return domain.url === url;
+    })) {
+        _webviews.forEach(function (webview) {
+            addOriginAccessWhitelistEntry(webview, url, WW_URI, true);
+
+            _domains.forEach(function (domain) {
+                addOriginAccessWhitelistEntry(webview, domain.url, url, allowSubDomains);
+                addOriginAccessWhitelistEntry(webview, url, domain.url, domain.allowSubDomains);
+            });
+
+        });
+
+        _domains.push({
+            url: url,
+            allowSubDomains: allowSubDomains
+        });
+    }
+}
+
+function initializeDomains() {
+    var accessElements = config.accessList;
+
+    accessElements.forEach(function (element, index, array) {
+        var uri = (element.uri === 'WIDGET_LOCAL' ? LOCAL_URI : element.uri);
+        addDomain(uri, !!element.allowSubDomain);
+    });
+}
+
+function initializaWebview(webview) {
+    //Always allow file access from local and let the OS deal with permissions
+    addOriginAccessWhitelistEntry(webview, LOCAL_URI, FILE_URI, true);
+    addOriginAccessWhitelistEntry(webview, FILE_URI, LOCAL_URI, true);
+    //Always allow LOCAL access to URIs
+    addOriginAccessWhitelistEntry(webview, LOCAL_URI, WW_URI, true);
+
+    _domains.forEach(function (domain, domainIndex, domainArray) {
+        var i,
+            nextDomain;
+
+        if (domain.uri !== LOCAL_URI) {
+            addOriginAccessWhitelistEntry(webview, domain.url, WW_URI, true);
+        }
+
+        for (i = domainIndex + 1; i < domainArray.length; i++) {
+            nextDomain = domainArray[i];
+            addOriginAccessWhitelistEntry(webview, domain.url, nextDomain.url, nextDomain.allowSubDomains);
+            addOriginAccessWhitelistEntry(webview, nextDomain.url, domain.url, domain.allowSubDomains);
+        }
+    });
+
+}
+
+module.exports = {
+
+    addWebView: function (webview) {
+        if (_webviews.indexOf(webview) === -1) {
+            _webviews.push(webview);
+            initializaWebview(webview);
+            if (!_isInitialized) {
+                initializeDomains();
+                _isInitialized = true;
+            }
+        }
+    },
+
+    addOriginAccess: function (origin, allowSubDomains) {
+        if (!_isInitialized) {
+            initializeDomains();
+            _isInitialized = true;
+        }
+        addDomain(origin, allowSubDomains);
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/policy/whitelist.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/policy/whitelist.js b/lib/cordova-blackberry/framework/lib/policy/whitelist.js
new file mode 100644
index 0000000..dcfbc3c
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/policy/whitelist.js
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var WebFolderAccess = require("./folderAccess").WebFolderAccess,
+    util = require("../utils");
+
+function _isLocalAccess(access) {
+    return access && access.uri === "WIDGET_LOCAL";
+}
+
+function _isMatch(access, requestURI) {
+    // Look for local first
+    if (_isLocalAccess(access)) {
+        // Local access always allowed
+        //THIS USED TO RETURN TRUE FOR FILE ACCESS
+        //I HAVE TURNED IT OFF BECAUSE IT MAKES NO SENSE THAT LOCAL ACCESS ALWAYS MATCHES FILE ACCESS
+        return (util.isLocalURI(requestURI));
+    } else if (util.isDataURI(requestURI)) {
+        // Check for data url
+        // data urls are allowed
+        return true;
+    }
+
+    // Based on widgets 1.0 (access control)
+    // http://www.w3.org/TR/2009/WD-widgets-access-20090618/#rfc3987
+    var refURI = util.parseUri(access.uri),
+        allowSub = access.allowSubDomain;
+
+    if (!requestURI.path) {
+        requestURI.path = "/";
+    }
+
+    // Start comparison based on widget spec.
+    // 1. Compare scheme
+    if (refURI.scheme.toLowerCase() !== requestURI.scheme.toLowerCase()) {
+        return false;
+    }
+
+    // 2. Compare host - if subdoman is false, host must match exactly
+    // (referenceURI MUST HAVE host specified - not null.)
+    // Special Case: Ignore this condition if we are dealing with file://
+    if (!requestURI.authority && !util.isFileURI(requestURI)) {
+        return false;
+    }
+
+    if (!allowSub && refURI.host.toLowerCase() !== requestURI.host.toLowerCase()) {
+        return false;
+    }
+
+    // 3. Compare host - if subdomain is true, check for subdomain or match
+    if (allowSub && !util.endsWith(requestURI.host.toLowerCase(), "." + refURI.host.toLowerCase()) &&
+        requestURI.host.toLowerCase() !== refURI.host.toLowerCase()) {
+        return false;
+    }
+
+    // 4. Compare port
+    if (refURI.port && refURI.port !== requestURI.port) {
+        return false;
+    }
+
+    // 5.  Compare path+query
+    if (!util.startsWith(requestURI.path.toLowerCase(), refURI.path.toLowerCase()) && refURI.query !== "*") {
+        return false;
+    }
+
+    return true;
+}
+
+function _getAccessForPathAndQuery(folderAccess, path, query) {
+    if (folderAccess) {
+        if (!query) {
+            return folderAccess.getAccess(path);
+        } else {
+            return folderAccess.getAccess(path + "?" + query);
+        }
+    }
+
+    return null;
+}
+
+function AccessManager(config) {
+    config = config || require("../config");
+
+    this._accessList = config.accessList;
+    this._hasGlobalAccess = config.hasMultiAccess;
+    this._authorityCollection = null;
+    this._localAccess = null;
+}
+
+AccessManager.prototype.getFolderAccess = function (scheme, authority) {
+    var key = scheme + "://" + authority;
+    key = key.toLowerCase();
+
+    if (this._authorityCollection.hasOwnProperty(key)) {
+        return this._authorityCollection[key];
+    }
+
+    return null;
+};
+
+AccessManager.prototype.putFolderAccess = function (scheme, authority, folderAccess) {
+    var key = scheme + "://" + authority;
+    key = key.toLowerCase();
+    this._authorityCollection[key] = folderAccess;
+};
+
+AccessManager.prototype.initializeAuthCollection = function () {
+    var folderAccess, currentURI, that = this;
+
+    if (!this._authorityCollection) {
+        this._authorityCollection = {};
+
+        if (this._accessList) {
+            this._accessList.forEach(function (access) {
+                if (_isLocalAccess(access)) {
+                    that._localAccess = access;
+                } else {
+                    currentURI = util.parseUri(access.uri);
+
+                    // Check the authority collection to see if the authority item
+                    // we want already exists
+                    folderAccess = that.getFolderAccess(currentURI.scheme, currentURI.authority) || new WebFolderAccess();
+
+                    // Add folder path access to the authority item
+                    if (!currentURI.query) {
+                        folderAccess.addAccess(currentURI.path, access);
+                    } else {
+                        folderAccess.addAccess(currentURI.path + "?" + currentURI.query, access);
+                    }
+
+                    that.putFolderAccess(currentURI.scheme, currentURI.authority, folderAccess);
+                }
+            });
+        }
+    }
+};
+
+AccessManager.prototype.authorityCheck = function (port, scheme, authority) {
+    var originalAuthority = authority;
+
+    if (port) {
+        // If authority has a specific port, and the collection does not have an access matches
+        // the exact authority, strip port from authority to see if there is a match
+        if (!this.getFolderAccess(scheme, authority)) {
+            authority = authority.slice(0, authority.lastIndexOf(":"));
+            authority = this.authorityCheck("", scheme, authority);
+        }
+
+        //If no successful match was found without the port, reset the authority and try with it
+        if (!this.getFolderAccess(scheme, authority)) {
+            authority = originalAuthority;
+        }
+    }
+
+    if (authority.indexOf(".") === -1) {
+        // If authority is computer name, must have exact match in collection
+        if (!this.getFolderAccess(scheme, authority)) {
+            return "";
+        }
+
+        return authority;
+    }
+
+    while (authority && !this.getFolderAccess(scheme, authority)) {
+        if (authority.indexOf(".") === -1) {
+            return "";
+        }
+        authority = authority.substring(authority.indexOf(".") + 1);
+    }
+
+    return authority;
+};
+
+AccessManager.prototype.getFromFolderAccess = function (folderAccess, requestURI) {
+    var fetchedAccess = null,
+        scheme = requestURI.scheme,
+        authority = requestURI.authority,
+        path = requestURI.path,
+        query = requestURI.query,
+        prevAuthority;
+
+    if (!path) {
+        fetchedAccess = folderAccess.getAccess("/");
+    } else {
+        fetchedAccess = _getAccessForPathAndQuery(folderAccess, path, query);
+    }
+
+    // Make sure we've got the right one
+    while (!fetchedAccess || !_isMatch(fetchedAccess, requestURI)) {
+        // There was an auth url that matched, but didnt match the folder structure
+        // Try the next level up
+        prevAuthority = authority;
+        authority = authority.substring(authority.indexOf(".") + 1);
+        //If authority hasn't changed, then this loop will continue endlessly because nothing else has changed
+        //This will happen when an element has the same authority but no folder access.
+        if (prevAuthority === authority) {
+            return null;
+        }
+
+        // Check for an authority string that has an existing key
+        authority = this.authorityCheck(requestURI.port, scheme, authority);
+        if (!authority) {
+            return null;
+        }
+
+        // Retrieve access set for the specified authority
+        folderAccess = this.getFolderAccess(scheme, authority);
+
+        // Special case: no access element was found for a file protocol request.
+        // This is added since file protocol was allowed through the above check
+        if (scheme === "file" && !folderAccess) {
+            return null;
+        }
+
+        fetchedAccess = _getAccessForPathAndQuery(folderAccess, path, query);
+    }
+
+    return fetchedAccess;
+};
+
+AccessManager.prototype.getAccessByUrl = function (url) {
+    var requestURI = util.parseUri(url),
+        authority = requestURI.authority,
+        scheme = requestURI.scheme,
+        folderAccess,
+        fetchedAccess;
+
+    if (util.isAbsoluteURI(requestURI)) {
+        // Initialize authority collection if it does not yet exist
+        this.initializeAuthCollection();
+
+        // Start with the full authority path and check if an access exists for that path
+        // If it does not exist, remove the first section of the authority path and try again
+
+        // Check for an authority string that has an existing key
+        // Special case: Allow file, and local protocol to proceed without an authority
+        authority = this.authorityCheck(requestURI.port, scheme, authority);
+        if (!authority && !(scheme === "file" || scheme === "local" || scheme === "data")) {
+            return null;
+        }
+        // Retrieve access set for the specified authority
+        folderAccess = this.getFolderAccess(scheme, authority);
+
+        // Special case: no access was found for a file protocol request
+        // This is added since file protocol was allowed through the above check
+        if (scheme === "file" && !folderAccess) {
+            return null;
+        } else if (scheme === "local" && !folderAccess) {
+            // If no access element is found with local URI, use local access for this request
+            return this._localAccess;
+        } else if (scheme === "data") {
+            // Always allow data-uris
+            return true;
+        }
+
+        fetchedAccess = this.getFromFolderAccess(folderAccess, requestURI);
+
+        if (fetchedAccess) {
+            return fetchedAccess;
+        } else if (this._localAccess && _isMatch(this._localAccess, requestURI)) {
+            // If we cannot find a more specific access for this local URI, use local access
+            return this._localAccess;
+        } else if (folderAccess && _isMatch(folderAccess, requestURI)) {
+            return folderAccess;
+        }
+    }
+
+    return null;
+};
+
+AccessManager.prototype.hasGlobalAccess = function () {
+    return this._hasGlobalAccess;
+};
+
+function Whitelist(config) {
+    this._mgr = new AccessManager(config);
+}
+
+Whitelist.prototype.getFeaturesForUrl = function (url) {
+    var access = this._mgr.getAccessByUrl(url),
+        featureIds = [];
+
+    if (access && access.features) {
+        access.features.forEach(function (elem) {
+            featureIds.push(elem.id);
+        });
+    }
+
+    return featureIds;
+};
+
+Whitelist.prototype.isFeatureAllowed = function (url, feature) {
+    var features = this.getFeaturesForUrl(url);
+
+    return !!features && features.reduce(function (found, current) {
+        return found || current === feature;
+    }, false);
+};
+
+Whitelist.prototype.isAccessAllowed = function (url, isXHR) {
+    return (this._mgr.hasGlobalAccess() && !isXHR) || !!this._mgr.getAccessByUrl(url);
+};
+
+exports.Whitelist = Whitelist;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/server.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/server.js b/lib/cordova-blackberry/framework/lib/server.js
new file mode 100644
index 0000000..15b95b0
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/server.js
@@ -0,0 +1,121 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var DEFAULT_SERVICE = "default",
+    DEFAULT_ACTION = "exec";
+
+function rebuildRequest(req) {
+    var originalURL = req.params.service + "/" +
+            req.params.action +
+            (req.params.ext ? "/" + req.params.ext  : "") +
+            (req.params.method ? "/" + req.params.method : "") +
+            (req.params.args ? "?" + req.params.args : ""),
+        tokens = originalURL.split('/'),
+        //Handle the case where the method is multi-level
+        finalToken = (tokens[1] && tokens.length > 2) ? tokens.slice(1).join('/') : tokens[1],
+        args = null;
+
+    // set args
+    if (finalToken && finalToken.indexOf("?") >= 0) {
+        // Re-split args
+        args = finalToken.split("?")[1];
+    }
+
+    return {
+        params : {
+            service : DEFAULT_SERVICE,
+            action : DEFAULT_ACTION,
+            ext : tokens[0],
+            method : (finalToken && finalToken.indexOf("?") >= 0) ? finalToken.split("?")[0] : finalToken,
+            args : args
+        },
+        body : req.body,
+        origin : req.origin
+    };
+}
+
+function parseArgs(req) {
+    var args = null,
+        params;
+    // set args
+    if (req.params.args && typeof req.params.args === "string") {
+        // GET querystring to json
+        params = req.params.args.split("&");
+        if (params) {
+            args = {};
+            params.forEach(function (param) {
+                var parts = param.split("=");
+                args[parts[0]] = parts[1];
+            });
+        }
+    } else {
+        // POST body to json
+        if (req.body) {
+            args = JSON.parse(req.body);
+        }
+    }
+    req.params.args = args;
+}
+
+module.exports = {
+    handle: function (req, res, sourceWebview, config) {
+        try {
+            var pluginName = "lib/plugins/" + req.params.service,
+                plugin;
+
+            if (frameworkModules.indexOf(pluginName + ".js") === -1) {
+                pluginName = "lib/plugins/" + DEFAULT_SERVICE;
+                req = rebuildRequest(req);
+            }
+
+            parseArgs(req);
+
+            //Updating because some versions of node only work with relative paths
+            pluginName = pluginName.replace('lib', '.');
+
+            plugin = require("./utils").loadModule(pluginName);
+
+            plugin[req.params.action](req,
+            function (result) {
+                res.send(200, encodeURIComponent(JSON.stringify({
+                    code: 42,
+                    data: result
+                })));
+            },
+            function (code, error, httpCode) {
+                if (!httpCode) {
+                    httpCode = 200;
+                }
+
+                res.send(httpCode, encodeURIComponent(JSON.stringify({
+                    code: Math.abs(code) * -1 || -1,
+                    data: null,
+                    msg: error
+                })));
+            },
+            req.params.args,
+            {
+                "request": req,
+                "response": res,
+                "webview": sourceWebview,
+                "config": config
+            });
+        } catch (e) {
+            console.error(e);
+            res.send(404, "can't find the stuff");
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/utils.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/utils.js b/lib/cordova-blackberry/framework/lib/utils.js
new file mode 100644
index 0000000..4ab008a
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/utils.js
@@ -0,0 +1,549 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var self,
+    exception = require('./exception');
+
+function S4() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+}
+
+self = module.exports = {
+    validateNumberOfArguments: function (lowerBound, upperBound, numberOfArguments, customExceptionType, customExceptionMessage, customExceptionObject) {
+
+        customExceptionMessage = customExceptionMessage || "";
+
+        if (arguments.length < 3 || arguments.length > 6) {
+            exception.raise(exception.types.Argument, "Wrong number of arguments when calling: validateNumberOfArguments()");
+        }
+
+        if (isNaN(lowerBound) && isNaN(upperBound) && isNaN(numberOfArguments)) {
+            exception.raise(exception.types.ArgumentType, "(validateNumberOfArguments) Arguments are not numbers");
+        }
+
+        lowerBound = parseInt(lowerBound, 10);
+        upperBound = parseInt(upperBound, 10);
+        numberOfArguments = parseInt(numberOfArguments, 10);
+
+        if (numberOfArguments < lowerBound || numberOfArguments > upperBound) {
+            exception.raise((customExceptionType || exception.types.ArgumentLength), (customExceptionMessage + "\n\nWrong number of arguments"), customExceptionObject);
+        }
+
+    },
+
+    validateArgumentType: function (arg, argType, customExceptionType, customExceptionMessage, customExceptionObject) {
+        var invalidArg = false,
+            msg;
+
+        switch (argType) {
+        case "array":
+            if (!arg instanceof Array) {
+                invalidArg = true;
+            }
+            break;
+        case "date":
+            if (!arg instanceof Date) {
+                invalidArg = true;
+            }
+            break;
+        case "integer":
+            if (typeof arg === "number") {
+                if (arg !== Math.floor(arg)) {
+                    invalidArg = true;
+                }
+            }
+            else {
+                invalidArg = true;
+            }
+            break;
+        default:
+            if (typeof arg !== argType) {
+                invalidArg = true;
+            }
+            break;
+        }
+
+        if (invalidArg) {
+            msg = customExceptionMessage +  ("\n\nInvalid Argument type. argument: " + arg + " ==> was expected to be of type: " + argType);
+            exception.raise((customExceptionType || exception.types.ArgumentType), msg, customExceptionObject);
+        }
+    },
+
+    validateMultipleArgumentTypes: function (argArray, argTypeArray, customExceptionType, customExceptionMessage, customExceptionObject) {
+        for (var i = 0; i < argArray.length; i++) {
+            this.validateArgumentType(argArray[i], argTypeArray[i], customExceptionType, customExceptionMessage, customExceptionObject);
+        }
+    },
+
+    arrayContains: function (array, obj) {
+        var i = array.length;
+        while (i--) {
+            if (array[i] === obj) {
+                return true;
+            }
+        }
+        return false;
+    },
+
+    some: function (obj, predicate, scope) {
+        if (obj instanceof Array) {
+            return obj.some(predicate, scope);
+        }
+        else {
+            var values = self.map(obj, predicate, scope);
+
+            return self.reduce(values, function (some, value) {
+                return value ? value : some;
+            }, false);
+        }
+    },
+
+    count: function (obj) {
+        return self.sum(obj, function (total) {
+            return 1;
+        });
+    },
+
+    sum: function (obj, selector, scope) {
+        var values = self.map(obj, selector, scope);
+        return self.reduce(values, function (total, value) {
+            return total + value;
+        });
+    },
+
+    max: function (obj, selector, scope) {
+        var values = self.map(obj, selector, scope);
+        return self.reduce(values, function (max, value) {
+            return max < value ? value : max;
+        }, Number.MIN_VALUE);
+    },
+
+    min: function (obj, selector, scope) {
+        var values = self.map(obj, selector, scope);
+        return self.reduce(values, function (min, value) {
+            return min > value ? value : min;
+        }, Number.MAX_VALUE);
+    },
+
+    forEach: function (obj, action, scope) {
+        if (obj instanceof Array) {
+            return obj.forEach(action, scope);
+        }
+        else {
+            self.map(obj, action, scope);
+        }
+    },
+
+    filter: function (obj, predicate, scope) {
+        if (obj instanceof Array) {
+            return obj.filter(predicate, scope);
+        }
+        else {
+            var result = [];
+            self.forEach(obj, function (value, index) {
+                if (predicate.apply(scope, [value, index])) {
+                    result.push(value);
+                }
+
+            }, scope);
+
+            return result;
+        }
+    },
+
+    reduce: function (obj, func, init, scope) {
+        var i,
+            initial = init === undefined ? 0 : init,
+            result = initial;
+
+
+        if (obj instanceof Array) {
+            return obj.reduce(func, initial);
+        }
+        else if (obj instanceof NamedNodeMap) {
+            for (i = 0; i < obj.length; i++) {
+                result = func.apply(scope, [result, obj[i], i]);
+            }
+        }
+        else {
+            for (i in obj) {
+                if (obj.hasOwnProperty(i)) {
+                    result = func.apply(scope, [result, obj[i], i]);
+                }
+            }
+        }
+
+        return result;
+
+    },
+
+    map: function (obj, func, scope) {
+        var i,
+            returnVal = null,
+            result = [];
+
+        if (obj instanceof Array) {
+            return obj.map(func, scope);
+        }
+        else if (obj instanceof NamedNodeMap) {
+            for (i = 0; i < obj.length; i++) {
+                returnVal = func.apply(scope, [obj[i], i]);
+                result.push(returnVal);
+            }
+        }
+        else {
+            for (i in obj) {
+                if (obj.hasOwnProperty(i)) {
+                    returnVal = func.apply(scope, [obj[i], i]);
+                    result.push(returnVal);
+                }
+            }
+        }
+
+        return result;
+    },
+
+    series: function (tasks, callback) {
+
+        var execute = function () {
+            var args = [],
+                task;
+
+            if (tasks.length) {
+                task = tasks.shift();
+                args = args.concat(task.args).concat(execute);
+                task.func.apply(this, args);
+            }
+            else {
+                callback.func.apply(this, callback.args);
+            }
+        };
+
+        execute();
+    },
+
+    regexSanitize: function (regexString) {
+        return regexString.replace("^", "\\^")
+                    .replace("$", "\\$")
+                    .replace("(", "\\(")
+                    .replace(")", "\\)")
+                    .replace("<", "\\<")
+                    .replace("[", "\\[")
+                    .replace("{", "\\{")
+                    .replace(/\\/, "\\\\")
+                    .replace("|", "\\|")
+                    .replace(">", "\\>")
+                    .replace(".", "\\.")
+                    .replace("*", "\\*")
+                    .replace("+", "\\+")
+                    .replace("?", "\\?");
+    },
+
+    find: function (comparison, collection, startInx, endInx, callback) {
+        var results = [],
+            compare = function (s, pattern) {
+
+                if (typeof(s) !== "string" || pattern === null) {
+                    return s === pattern;
+                }
+
+                var regex = pattern.replace(/\./g, "\\.")
+                                   .replace(/\^/g, "\\^")
+                                   .replace(/\*/g, ".*")
+                                   .replace(/\\\.\*/g, "\\*");
+
+                regex = "^".concat(regex, "$");
+
+                return !!s.match(new RegExp(regex, "i"));
+            };
+
+        self.forEach(collection, function (c) {
+            var match,
+                fail = false;
+
+            self.forEach(comparison, function (value, key) {
+                if (!fail && value !== undefined) {
+
+                    if (compare(c[key], value)) {
+                        match = c;
+                    }
+                    else {
+                        fail = true;
+                        match = null;
+                    }
+                }
+            });
+
+            if (match) {
+                results.push(match);
+            }
+        });
+
+        if (callback) {
+            if (startInx === undefined) {
+                startInx = 0;
+            }
+            if (endInx === undefined) {
+                endInx = results.length;
+            }
+            if (startInx === endInx) {
+                endInx = startInx + 1;
+            }
+
+            callback.apply(null, [results.slice(startInx, endInx)]);
+        }
+    },
+
+    mixin: function (mixin, to) {
+        Object.getOwnPropertyNames(mixin).forEach(function (prop) {
+            if (Object.hasOwnProperty.call(mixin, prop)) {
+                Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(mixin, prop));
+            }
+        });
+        return to;
+    },
+
+    copy: function (obj) {
+        var i,
+            newObj = (obj === null ? false : global.toString.call(obj) === "[object Array]") ? [] : {};
+
+        if (typeof obj === 'number' ||
+            typeof obj === 'string' ||
+            typeof obj === 'boolean' ||
+            obj === null ||
+            obj === undefined) {
+            return obj;
+        }
+
+        if (obj instanceof Date) {
+            return new Date(obj);
+        }
+
+        if (obj instanceof RegExp) {
+            return new RegExp(obj);
+        }
+
+        for (i in obj) {
+            if (obj.hasOwnProperty(i)) {
+                if (obj[i] && typeof obj[i] === "object") {
+                    if (obj[i] instanceof Date) {
+                        newObj[i] = obj[i];
+                    }
+                    else {
+                        newObj[i] = self.copy(obj[i]);
+                    }
+                }
+                else {
+                    newObj[i] = obj[i];
+                }
+            }
+        }
+
+        return newObj;
+    },
+
+    startsWith : function (str, substr) {
+        return str.indexOf(substr) === 0;
+    },
+
+    endsWith : function (str, substr) {
+        return str.indexOf(substr, str.length - substr.length) !== -1;
+    },
+
+    parseUri : function (str) {
+        var i, uri = {},
+            key = [ "source", "scheme", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor" ],
+            matcher = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(str);
+
+        for (i = key.length - 1; i >= 0; i--) {
+            uri[key[i]] = matcher[i] || "";
+        }
+
+        return uri;
+    },
+
+    // uri - output from parseUri
+    isAbsoluteURI : function (uri) {
+        if (uri && uri.source) {
+            return uri.relative !== uri.source;
+        }
+
+        return false;
+    },
+
+    fileNameToImageMIME : function (fileName) {
+
+        var extensionsToMIME = {},
+            ext;
+
+        extensionsToMIME.png = 'image/png';
+        extensionsToMIME.jpg = 'image/jpeg';
+        extensionsToMIME.jpe = 'image/jpeg';
+        extensionsToMIME.jpeg = 'image/jpeg';
+        extensionsToMIME.gif = 'image/gif';
+        extensionsToMIME.bmp = 'image/bmp';
+        extensionsToMIME.bm = 'image/bmp';
+        extensionsToMIME.svg = 'image/svg+xml';
+        extensionsToMIME.tif = 'image/tiff';
+        extensionsToMIME.tiff = 'image/tiff';
+
+        ext = fileName.split('.').pop();
+        return extensionsToMIME[ext];
+    },
+
+    isLocalURI : function (uri) {
+        return uri && uri.scheme && "local:///".indexOf(uri.scheme.toLowerCase()) !== -1;
+    },
+
+    isFileURI : function (uri) {
+        return uri && uri.scheme && "file://".indexOf(uri.scheme.toLowerCase()) !== -1;
+    },
+
+    isHttpURI : function (uri) {
+        return uri && uri.scheme && "http://".indexOf(uri.scheme.toLowerCase()) !== -1;
+    },
+
+    isHttpsURI : function (uri) {
+        return uri && uri.scheme && "https://".indexOf(uri.scheme.toLowerCase()) !== -1;
+    },
+
+    // Checks if the specified uri starts with 'data:'
+    isDataURI : function (uri) {
+        return uri && uri.scheme && "data:".indexOf(uri.scheme.toLowerCase()) !== -1;
+    },
+
+    performExec : function (featureId, property, args) {
+        var result;
+
+        window.webworks.exec(function (data, response) {
+            result = data;
+        }, function (data, response) {
+            throw data;
+        }, featureId, property, args, true);
+
+        return result;
+    },
+
+    inNode : function () {
+        return !!require.resolve;
+    },
+
+    requireWebview : function () {
+        return require("./webview");
+    },
+    convertDataToBinary : function (data, dataEncoding) {
+        var rawData,
+            uint8Array,
+            i;
+
+        if (data) {
+            if (dataEncoding.toLowerCase() === "base64") {
+                rawData = window.atob(data);
+            }
+            else {
+                rawData = data;
+            }
+
+            uint8Array = new Uint8Array(new ArrayBuffer(rawData.length));
+
+            for (i = 0; i < uint8Array.length; i++) {
+                uint8Array[i] = rawData.charCodeAt(i);
+            }
+
+            return uint8Array.buffer;
+        }
+    },
+    getBlobWithArrayBufferAsData : function (data, dataEncoding) {
+        var rawData,
+            blobBuilderObj = new window.WebKitBlobBuilder();
+        rawData = this.convertDataToBinary(data, dataEncoding);
+        blobBuilderObj.append(rawData);
+
+        return blobBuilderObj.getBlob("arraybuffer");
+    },
+    loadModule: function (module) {
+        return require(module);
+    },
+    loadExtensionModule: function (plugin, path) {
+        if (plugin && path) {
+            return require("../plugin/" + plugin + "/" + path);
+        } else {
+            return null;
+        }
+    },
+    hasPermission: function (config, permission) {
+        if (config && config.permissions && config.permissions.length) {
+            return config.permissions.indexOf(permission) >= 0;
+        }
+
+        return false;
+    },
+    guid: function () {
+        return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+    },
+    getURIPrefix: function () {
+        return "http://localhost:8472/";
+    },
+    translatePath: function (path) {
+        if (path.indexOf("local:///") === 0) {
+            var sourceDir = window.qnx.webplatform.getApplication().getEnv("HOME"); //leading slashes need to be removed
+            path = "file:///" + sourceDir.replace(/^\/*/, '') + "/../app/native/" + path.replace(/local:\/\/\//, '');
+        }
+        return path;
+    },
+    invokeInBrowser: function (url) {
+        var request = {
+            uri: url,
+            target: "sys.browser"
+        };
+        window.qnx.webplatform.getApplication().invocation.invoke(request);
+    },
+    isPersonal: function () {
+        return window.qnx.webplatform.getApplication().getEnv("PERIMETER") === "personal";
+    },
+    deepclone: function (obj) {
+        var newObj = obj instanceof Array ? [] : {},
+            key;
+
+        if (typeof obj === 'number' ||
+                typeof obj === 'string' ||
+                typeof obj === 'boolean' ||
+                obj === null ||
+                obj === undefined) {
+            return obj;
+        }
+
+        if (obj instanceof Date) {
+            return new Date(obj);
+        }
+
+        if (obj instanceof RegExp) {
+            return new RegExp(obj);
+        }
+
+        for (key in obj) {
+            if (obj.hasOwnProperty(key)) {
+                if (obj[key] && typeof obj[key] === "object") {
+                    newObj[key] = self.deepclone(obj[key]);
+                } else {
+                    newObj[key] = obj[key];
+                }
+            }
+        }
+
+        return newObj;
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/webkitEvent.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/webkitEvent.js b/lib/cordova-blackberry/framework/lib/webkitEvent.js
new file mode 100644
index 0000000..0f4bef7
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/webkitEvent.js
@@ -0,0 +1,87 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var utils = require('./utils'),
+    exception = require('./exception'),
+    _listeners = {};
+
+function _on(eventType, listener, scope, once) {
+    if (!eventType) {
+        throw "eventType must be truthy";
+    }
+    _listeners[eventType] = _listeners[eventType] || [];
+    _listeners[eventType].push({
+        func: listener,
+        scope: scope,
+        once: !!once
+    });
+}
+
+function _trigger(listener, args, sync) {
+    try {
+        if (sync) {
+            listener.func.apply(listener.scope, args);
+        }
+        else {
+            setTimeout(function () {
+                listener.func.apply(listener.scope, args);
+            }, 1);
+        }
+    }
+    catch (e) {
+        exception.handle(e);
+    }
+}
+
+module.exports = {
+    on: function (eventType, listener, scope) {
+        _on(eventType, listener, scope, false);
+    },
+
+    once: function (eventType, listener, scope) {
+        _on(eventType, listener, scope, true);
+    },
+
+    trigger: function (eventType, args, sync) {
+        args = args || [];
+        sync = sync || false;
+
+        var listeners = _listeners[eventType];
+
+        if (listeners) {
+            listeners.forEach(function (listener) {
+                _trigger(listener, args, sync);
+            });
+
+            _listeners[eventType] = listeners.filter(function (listener) {
+                return !listener.once;
+            });
+        }
+    },
+
+    eventHasSubscriber: function (eventType) {
+        return !!_listeners[eventType];
+    },
+
+    getEventSubscribers: function (eventType) {
+        return utils.copy(_listeners[eventType]) || [];
+    },
+
+    clear: function (eventType) {
+        if (eventType) {
+            delete _listeners[eventType];
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/lib/webkitHandlers/networkResourceRequested.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/webkitHandlers/networkResourceRequested.js b/lib/cordova-blackberry/framework/lib/webkitHandlers/networkResourceRequested.js
new file mode 100644
index 0000000..759c8bd
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/webkitHandlers/networkResourceRequested.js
@@ -0,0 +1,126 @@
+/*
+ *  Copyright 2012 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var Whitelist = require('../policy/whitelist').Whitelist,
+    ACCEPT_RESPONSE = {setAction: "ACCEPT"},
+    DENY_RESPONSE = {setAction: "DENY"},
+    SUBSTITUTE_RESPONSE = {setAction: "SUBSTITUTE"},
+    utils = require('../utils');
+
+function _formMessage(url, origin, sid, body, securityOrigin, webview) {
+    var tokens = url.split(utils.getURIPrefix())[1].split("/"),
+        //Handle the case where the method is multi-level
+        finalToken = (tokens[3] && tokens.length > 4) ? tokens.slice(3).join('/') : tokens[3];
+
+    return {
+        request : {
+            params : {
+                service : tokens[0],
+                action : tokens[1],
+                ext : tokens[2],
+                method : (finalToken && finalToken.indexOf("?") >= 0) ? finalToken.split("?")[0] : finalToken,
+                args : (finalToken && finalToken.indexOf("?") >= 0) ? finalToken.split("?")[1] : null
+            },
+            body : body,
+            origin : origin,
+            securityOrigin: securityOrigin
+
+        },
+        response : {
+            send : function (code, data) {
+                var responseText;
+                if (typeof(data) === 'string') {
+                    responseText = data;
+                } else {
+                    responseText =  JSON.stringify(data);
+                }
+
+                webview.notifyOpen(sid, code, "OK");
+                webview.notifyHeaderReceived(sid, "Access-Control-Allow-Origin", "*");
+                webview.notifyHeaderReceived(sid, "Access-Control-Allow-Origin", securityOrigin);
+                webview.notifyHeaderReceived(sid, "Access-Control-Allow-Headers", "Content-Type");
+                webview.notifyDataReceived(sid, responseText, responseText.length);
+                webview.notifyDone(sid);
+            }
+        }
+    };
+}
+
+function networkResourceRequestedHandler(value) {
+    var config = require("./../config"),
+        obj = JSON.parse(value),
+        response,
+        url = obj.url,
+        body = obj.body,
+        whitelist = new Whitelist(),
+        server,
+        message,
+        sid = obj.streamId,
+        origin = obj.referrer,
+        securityOrigin = obj.securityOrigin,
+        isXHR = obj.targetType === "TargetIsXMLHTTPRequest",
+        //Assumes its a navigation request if the target is the main frame
+        isNav = obj.targetType === "TargetIsMainFrame",
+        hasAccess = whitelist.isAccessAllowed(url, isXHR),
+        deniedMsg;
+
+    //If the URL starts with the prefix then its a request from an API
+    //In this case we will hijack and give our own response
+    //Otherwise follow whitelisting rules
+    if (url.match("^" + utils.getURIPrefix())) {
+        server = require("../server");
+        message = _formMessage(url, origin, sid, body, securityOrigin, this.webview, config);
+        response = SUBSTITUTE_RESPONSE;
+        server.handle(message.request, message.response, this.webview);
+    } else {
+        //Whitelisting will not prevent navigation, ONLY we will
+        //Except when they've disabled web security
+        if (hasAccess || !config.enableWebSecurity) {
+            response = ACCEPT_RESPONSE;
+        } else {
+            response = DENY_RESPONSE;
+            url = utils.parseUri(url);
+            deniedMsg = "Access to \"" + url.source + "\" not allowed";
+
+            console.warn(deniedMsg);
+
+            //Denied navigation requests are sent to the inApp browser rather than an alert
+            if (isNav) {
+                if (config.enableChildWebView) {
+                    this.webview.uiWebView.childwebviewcontrols.open(url.source);
+                } else {
+                    utils.invokeInBrowser(url.source);
+                }
+            } else {
+                this.webview.executeJavaScript("alert('" + deniedMsg + "')");
+            }
+        }
+    }
+
+    if (response) {
+        return JSON.stringify(response);
+    }
+}
+
+function NetworkResourceRequestHandler(webview) {
+    this.webview = webview;
+    this.networkResourceRequestedHandler = networkResourceRequestedHandler.bind(this);
+}
+
+module.exports = {
+    createHandler: function (webview) {
+        return new NetworkResourceRequestHandler(webview);
+    }
+};