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:33 UTC

[12/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/webview.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/lib/webview.js b/lib/cordova-blackberry/framework/lib/webview.js
new file mode 100644
index 0000000..495dfbe
--- /dev/null
+++ b/lib/cordova-blackberry/framework/lib/webview.js
@@ -0,0 +1,271 @@
+/*
+ *  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 networkResourceRequested = require('./webkitHandlers/networkResourceRequested'),
+    utils = require('./utils'),
+    config = require('./config'),
+    webkitOriginAccess = require("./policy/webkitOriginAccess"),
+    CHROME_HEIGHT = 0,
+    OUT_OF_PROCESS = 1,
+    webview,
+    _webviewObj;
+
+webview =
+    {
+    create: function (ready) {
+        _webviewObj = window.qnx.webplatform.createWebView({processId: OUT_OF_PROCESS, defaultSendEventHandlers: ['onChooseFile', 'onOpenWindow'], defaultWebEventHandlers: ['InvokeRequestEvent']}, function () {
+            //Create webkit event handlers
+            var requestObj =  networkResourceRequested.createHandler(_webviewObj);
+
+            //Bind networkResourceRequested event so that everything works
+            _webviewObj.onNetworkResourceRequested = requestObj.networkResourceRequestedHandler;
+
+            webkitOriginAccess.addWebView(_webviewObj);
+
+            _webviewObj.visible = true;
+            _webviewObj.active = true;
+            _webviewObj.zOrder = 0;
+            _webviewObj.setGeometry(0, CHROME_HEIGHT, screen.width, screen.height - CHROME_HEIGHT);
+
+            if (typeof config.backgroundColor !== 'undefined') {
+                _webviewObj.backgroundColor = config.backgroundColor;
+            }
+
+            if (typeof config.customHeaders !== 'undefined') {
+                _webviewObj.extraHttpHeaders = config.customHeaders;
+            }
+
+            if (typeof config.userAgent !== 'undefined') {
+                _webviewObj.userAgent = config.userAgent;
+            }
+
+            _webviewObj.autoDeferNetworkingAndJavaScript = config.autoDeferNetworkingAndJavaScript;
+
+            /* Catch and trigger our custom HTML dialog */
+            _webviewObj.allowWebEvent("DialogRequested");
+
+            _webviewObj.addEventListener("DocumentLoadFinished", function () {
+                // show app window if auto hide splash screen is true, OR splash screen is not specified
+                // if auto hide is set to false explicitly but no splash screen is specified, should still show app window
+                // otherwise the app cannot be launched
+                if (config.autoHideSplashScreen || !config["rim:splash"]) {
+                    window.qnx.webplatform.getApplication().windowVisible = true;
+                }
+            });
+
+
+            if (ready && typeof ready === 'function') {
+                ready();
+            }
+
+            window.qnx.webplatform.getController().dispatchEvent("webview.initialized", [_webviewObj]);
+
+            // If content is not loaded, too bad open the visibility up.
+            setTimeout(function () {
+                if (config.autoHideSplashScreen || !config["rim:splash"]) {
+                    window.qnx.webplatform.getApplication().windowVisible = true;
+                }
+            }, 2500);
+        });
+
+    },
+
+    destroy: function () {
+        _webviewObj.destroy();
+    },
+
+    setURL: function (url) {
+        _webviewObj.url = url;
+    },
+
+    reload: function () {
+        _webviewObj.reload();
+    },
+
+    executeJavascript: function (js) {
+        _webviewObj.executeJavaScript(js);
+    },
+
+    addEventListener: function (eventName, callback) {
+        _webviewObj.addEventListener(eventName, callback);
+    },
+
+    removeEventListener: function (eventName, callback) {
+        _webviewObj.removeEventListener(eventName, callback);
+    },
+
+    windowGroup: function () {
+        return _webviewObj.windowGroup;
+    },
+
+    getGeometry: function () {
+        return this.geometry;
+    },
+
+    setGeometry: function (x, y, width, height) {
+        this.geometry = {x: x, y: y, w: width, h: height};
+        _webviewObj.setGeometry(x, y, width, height);
+    },
+
+    setApplicationOrientation: function (angle) {
+        _webviewObj.setApplicationOrientation(angle);
+    },
+
+    setExtraPluginDirectory: function (directory) {
+        _webviewObj.setExtraPluginDirectory(directory);
+    },
+
+    setEnablePlugins: function (enablePlugins) {
+        _webviewObj.pluginsEnabled = enablePlugins;
+    },
+
+    getEnablePlugins: function () {
+        return _webviewObj.pluginsEnabled;
+    },
+
+    notifyApplicationOrientationDone: function () {
+        _webviewObj.notifyApplicationOrientationDone();
+    },
+
+    setSandbox: function (sandbox) {
+        _webviewObj.setFileSystemSandbox = sandbox;
+    },
+
+    getSandbox: function () {
+        return _webviewObj.setFileSystemSandbox;
+    },
+
+    downloadURL: function (url) {
+        _webviewObj.downloadURL(url);
+    },
+
+    handleContextMenuResponse: function (action) {
+        _webviewObj.handleContextMenuResponse(action);
+    },
+
+    allowGeolocation : function (url) {
+        _webviewObj.allowGeolocation(url);
+    },
+
+    disallowGeolocation : function (url) {
+        _webviewObj.disallowGeolocation(url);
+
+    },
+
+    addKnownSSLCertificate: function (url, certificateInfo) {
+        _webviewObj.addKnownSSLCertificate(url, certificateInfo);
+    },
+
+    continueSSLHandshaking: function (streamId, SSLAction) {
+        _webviewObj.continueSSLHandshaking(streamId, SSLAction);
+    },
+
+    getSensitivity: function () {
+        return _webviewObj.getSensitivity();
+    },
+
+    setSensitivity: function (sensitivity) {
+        return _webviewObj.setSensitivity(sensitivity);
+    },
+
+    getBackgroundColor: function () {
+        return _webviewObj.getBackgroundColor();
+    },
+
+    setBackgroundColor: function (backgroundColor) {
+        return _webviewObj.setBackgroundColor(backgroundColor);
+    },
+
+    getWebViewObj: function (webview) {
+        return _webviewObj;
+    },
+
+    setUIWebViewObj: function (webviewObj) {
+        _webviewObj.uiWebView = webviewObj;
+    },
+
+    allowUserMedia: function (evtId, cameraName) {
+        _webviewObj.allowUserMedia(evtId, cameraName);
+    },
+
+    disallowUserMedia: function (evtId) {
+        _webviewObj.disallowUserMedia(evtId);
+    }
+};
+
+webview.__defineGetter__('id', function () {
+    if (_webviewObj) {
+        return _webviewObj.id;
+    }
+});
+
+webview.__defineGetter__('enableCrossSiteXHR', function () {
+    return _webviewObj.enableCrossSiteXHR;
+});
+
+webview.__defineSetter__('enableCrossSiteXHR', function (shouldEnable) {
+    _webviewObj.enableCrossSiteXHR = !!shouldEnable;
+});
+
+webview.__defineGetter__('processId', function () {
+    return _webviewObj.processId;
+});
+
+webview.__defineSetter__('onOpenWindow', function (input) {
+    _webviewObj.onOpenWindow = input;
+});
+
+webview.__defineSetter__('onCloseWindow', function (input) {
+    _webviewObj.onCloseWindow = input;
+});
+
+webview.__defineSetter__('onDestroyWindow', function (input) {
+    _webviewObj.onDestroyWindow = input;
+});
+
+webview.__defineSetter__('onDialogRequested', function (input) {
+    _webviewObj.onDialogRequested = input;
+});
+
+webview.__defineSetter__('onGeolocationPermissionRequest', function (input) {
+    _webviewObj.onGeolocationPermissionRequest = input;
+});
+
+webview.__defineSetter__('onSSLHandshakingFailed', function (input) {
+    _webviewObj.onSSLHandshakingFailed = input;
+});
+
+webview.__defineSetter__('onPropertyCurrentContextEvent', function (input) {
+    _webviewObj.onPropertyCurrentContextEvent = input;
+});
+
+webview.__defineSetter__('onContextMenuRequestEvent', function (input) {
+    _webviewObj.onContextMenuRequestEvent = input;
+});
+
+webview.__defineSetter__('onContextMenuCancelEvent', function (input) {
+    _webviewObj.onContextMenuCancelEvent = input;
+});
+
+webview.__defineSetter__('onUserMediaRequest', function (input) {
+    _webviewObj.onUserMediaRequest = input;
+});
+
+webview.__defineSetter__('onChildWindowOpen', function (input) {
+    _webviewObj.onChildWindowOpen = input;
+});
+
+module.exports = webview;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/config.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/config.js b/lib/cordova-blackberry/framework/test/unit/lib/config.js
new file mode 100644
index 0000000..64e8f7e
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/config.js
@@ -0,0 +1,30 @@
+/*
+ * 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 srcPath = __dirname + '/../../../lib/';
+
+describe("Config", function () {
+    var config = require(srcPath + 'config.js');
+
+    it("verify user value is correctly mixed", function () {
+        expect(config.copyright).toEqual("@Rebecca");
+    });
+
+    it("verify default value is correctly mixed", function () {
+        expect(config.widgetExtensions).toEqual(null);
+    });
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/controllerWebView.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/controllerWebView.js b/lib/cordova-blackberry/framework/test/unit/lib/controllerWebView.js
new file mode 100644
index 0000000..003d276
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/controllerWebView.js
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+describe("controllerWebView", function () {
+    var controllerWebView = require('./../../../lib/controllerWebView'),
+        mockedController,
+        mockedInvocation,
+        mockedApplication;
+
+    beforeEach(function () {
+        mockedController = {
+            id: 42,
+            enableWebInspector: null,
+            enableCrossSiteXHR: null,
+            visible: null,
+            active: null,
+            setGeometry: jasmine.createSpy(),
+            setApplicationOrientation: jasmine.createSpy(),
+            notifyApplicationOrientationDone: jasmine.createSpy(),
+            publishRemoteFunction: jasmine.createSpy(),
+            dispatchEvent : jasmine.createSpy()
+        };
+        mockedInvocation = {
+            queryTargets: function (request, callback) {
+                callback("error", "results");
+            }
+        };
+        mockedApplication = {
+            invocation: mockedInvocation
+        };
+        GLOBAL.window = {
+            qnx: {
+                webplatform: {
+                    getController: function () {
+                        return mockedController;
+                    },
+                    getApplication: function () {
+                        return mockedApplication;
+                    }
+                }
+            }
+        };
+        GLOBAL.screen = {
+            width : 1024,
+            height: 768
+        };
+    });
+
+    describe("init", function () {
+        it("sets up the controllerWebview", function () {
+            controllerWebView.init({debugEnabled: true});
+            expect(mockedController.enableWebInspector).toEqual(true);
+            expect(mockedController.enableCrossSiteXHR).toEqual(true);
+            expect(mockedController.visible).toEqual(false);
+            expect(mockedController.active).toEqual(false);
+            expect(mockedController.setGeometry).toHaveBeenCalledWith(0, 0, screen.width, screen.height);
+        });
+
+        it("tests that the dispatch function is called properly", function () {
+            controllerWebView.init({debugEnabled: true});
+            controllerWebView.dispatchEvent('Awesome Event', ['these are agruments', 'another argument']);
+            expect(mockedController.dispatchEvent).toHaveBeenCalledWith('Awesome Event', ['these are agruments', 'another argument']);
+        });
+    });
+
+    describe("id", function () {
+        it("can get the id for the webiew", function () {
+            controllerWebView.init({debugEnabled: true});
+            expect(controllerWebView.id).toEqual(mockedController.id);
+        });
+    });
+
+    describe("geometry", function () {
+        it("can set geometry", function () {
+            controllerWebView.init({debugEnabled: true});
+            controllerWebView.setGeometry(0, 0, 100, 200);
+            expect(mockedController.setGeometry).toHaveBeenCalledWith(0, 0, 100, 200);
+        });
+    });
+
+    describe("application orientation", function () {
+        it("can set application orientation", function () {
+            controllerWebView.init({debugEnabled: true});
+            controllerWebView.setApplicationOrientation(90);
+            expect(mockedController.setApplicationOrientation).toHaveBeenCalledWith(90);
+        });
+
+        it("can notifyApplicationOrientationDone", function () {
+            controllerWebView.init({debugEnabled: true});
+            controllerWebView.notifyApplicationOrientationDone();
+            expect(mockedController.notifyApplicationOrientationDone).toHaveBeenCalled();
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/event.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/event.js b/lib/cordova-blackberry/framework/test/unit/lib/event.js
new file mode 100644
index 0000000..3d3e7fe
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/event.js
@@ -0,0 +1,139 @@
+/*
+ * 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 libRoot = __dirname + "/../../../lib/";
+
+describe("lib/event", function () {
+    var event = require(libRoot + "event"),
+        webview = require(libRoot + "webview"),
+        mockedWebview;
+
+    beforeEach(function () {
+        spyOn(webview, "executeJavascript");
+        mockedWebview = {
+            executeJavaScript: jasmine.createSpy(),
+            id: (new Date()).getTime()
+        };
+    });
+
+    describe("trigger", function () {
+
+
+        it("will trigger on the content webview when no webview is registered (for backwards compatability)", function () {
+            event.trigger("foo", {"id": 123});
+            expect(mockedWebview.executeJavaScript).not.toHaveBeenCalled();
+            expect(webview.executeJavascript).toHaveBeenCalled();
+        });
+
+        it("can invoke the webview execute javascript", function () {
+            var data = {"id": 123};
+            event.add({event: "foo", context: {addEventListener: jasmine.createSpy()}}, mockedWebview);
+            event.trigger("foo", data);
+            expect(mockedWebview.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([data]))) + "')");
+            expect(webview.executeJavascript).not.toHaveBeenCalled();
+            this.after(function () {
+                event.remove({event: "foo", context: {removeEventListener: jasmine.createSpy()}}, mockedWebview);
+            });
+        });
+
+        it("sends multiple arguments passed in across as a JSONified array", function () {
+            var args = [{"id": 123, "foo": "hello world", list: [1, 2, 3]}, "Grrrrrrr", "Arrrrg"];
+            event.add({event: "foo", context: {addEventListener: jasmine.createSpy()}}, mockedWebview);
+            event.trigger.apply(null, ["foo"].concat(args));
+            expect(mockedWebview.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify(args))) + "')");
+            expect(webview.executeJavascript).not.toHaveBeenCalled();
+            this.after(function () {
+                event.remove({event: "foo", context: {removeEventListener: jasmine.createSpy()}}, mockedWebview);
+            });
+        });
+
+        it("invokes on all webviews that have registered, but not those removed", function () {
+            var mockedWebview2 = {
+                    executeJavaScript: jasmine.createSpy(),
+                    id: mockedWebview.id - 42
+                },
+                mockedWebview3 = {
+                    executeJavaScript: jasmine.createSpy(),
+                    id: mockedWebview.id + 42
+                },
+                mockedWebview4 = {
+                    executeJavaScript: jasmine.createSpy(),
+                    id: mockedWebview.id * 42
+                };
+            event.add({event: "foo", context: {addEventListener: jasmine.createSpy()}}, mockedWebview);
+            event.add({event: "foo", context: {addEventListener: jasmine.createSpy()}}, mockedWebview2);
+            event.add({event: "foo", context: {addEventListener: jasmine.createSpy()}}, mockedWebview3);
+            event.trigger("foo", {"id": 123});
+            expect(mockedWebview.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview2.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview3.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview4.executeJavaScript).not.toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(webview.executeJavascript).not.toHaveBeenCalled();
+
+
+            event.remove({event: "foo", context: {removeEventListener: jasmine.createSpy()}}, mockedWebview3);
+            mockedWebview.executeJavaScript.reset();
+            mockedWebview2.executeJavaScript.reset();
+            mockedWebview3.executeJavaScript.reset();
+            mockedWebview4.executeJavaScript.reset();
+            event.trigger("foo", {"id": 123});
+            expect(mockedWebview.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview2.executeJavaScript).toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview3.executeJavaScript).not.toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(mockedWebview4.executeJavaScript).not.toHaveBeenCalledWith("webworks.event.trigger('foo', '" + escape(encodeURIComponent(JSON.stringify([{"id": 123}]))) + "')");
+            expect(webview.executeJavascript).not.toHaveBeenCalled();
+            this.after(function () {
+                event.remove({event: "foo", context: {removeEventListener: jasmine.createSpy()}}, mockedWebview);
+                event.remove({event: "foo", context: {removeEventListener: jasmine.createSpy()}}, mockedWebview2);
+            });
+        });
+
+    });
+
+    describe("add/remove would invoke action context", function () {
+        var action = {
+                context: {
+                    addEventListener: jasmine.createSpy(),
+                    removeEventListener: jasmine.createSpy()
+                },
+                event: "HELLO",
+                trigger: function () {}
+            };
+
+        beforeEach(function () {
+            action.context.addEventListener.reset();
+            action.context.removeEventListener.reset();
+        });
+
+        it("can invoke action context add listener", function () {
+            event.add(action, mockedWebview);
+            expect(action.context.addEventListener).toHaveBeenCalledWith(action.event, action.trigger);
+        });
+
+        it("will not invoke action context add listener when the action has a once field", function () {
+            action.once = true;
+            event.add(action, mockedWebview);
+            expect(action.context.addEventListener).not.toHaveBeenCalledWith(action.event, action.trigger);
+            this.after(function () {
+                delete action.once;
+            });
+        });
+
+        it("can invoke action context remove listener", function () {
+            event.remove(action, mockedWebview);
+            expect(action.context.removeEventListener).toHaveBeenCalledWith(action.event, action.trigger);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/events/applicationEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/events/applicationEvents.js b/lib/cordova-blackberry/framework/test/unit/lib/events/applicationEvents.js
new file mode 100644
index 0000000..81fa2e1
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/events/applicationEvents.js
@@ -0,0 +1,82 @@
+/*
+ * 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 _libDir = __dirname + "./../../../../lib/",
+    appEventPrefix = "application.",
+    appEvents,
+    mockedApplication;
+
+describe("lib/events/applicationEvents", function () {
+    beforeEach(function () {
+        mockedApplication = {
+            addEventListener: jasmine.createSpy("application addEventListener"),
+            removeEventListener: jasmine.createSpy("application removeEventListener")
+        };
+        GLOBAL.window = {
+            qnx: {
+                webplatform: {
+                    getApplication: function () {
+                        return mockedApplication;
+                    }
+                }
+            }
+        };
+        appEvents = require(_libDir + "events/applicationEvents");
+    });
+
+    afterEach(function () {
+        mockedApplication = null;
+        delete GLOBAL.window;
+        appEvents = null;
+        delete require.cache[require.resolve(_libDir + "events/applicationEvents")];
+    });
+
+    describe("addEventListener", function () {
+        it("adds event name with application prepended", function () {
+            var eventName = "MostAwesomeEventEver",
+                trigger = function () {};
+            appEvents.addEventListener(eventName, trigger);
+            expect(mockedApplication.addEventListener).toHaveBeenCalledWith(appEventPrefix + eventName, trigger);
+        });
+
+        it("warns in the console if the eventName is falsey", function () {
+            var eventName = false,
+                trigger = function () {};
+            spyOn(console, "warn");
+            appEvents.addEventListener(eventName, trigger);
+            expect(mockedApplication.addEventListener).not.toHaveBeenCalledWith(appEventPrefix + eventName, trigger);
+            expect(console.warn).toHaveBeenCalledWith(jasmine.any(String));
+        });
+    });
+
+    describe("removeEventListener", function () {
+        it("adds event name with application prepended", function () {
+            var eventName = "MostAwesomeEventEver",
+                trigger = function () {};
+            appEvents.removeEventListener(eventName, trigger);
+            expect(mockedApplication.removeEventListener).toHaveBeenCalledWith(appEventPrefix + eventName, trigger);
+        });
+
+        it("warns in the console if the eventName is falsey", function () {
+            var eventName = false,
+                trigger = function () {};
+            spyOn(console, "warn");
+            appEvents.removeEventListener(eventName, trigger);
+            expect(mockedApplication.removeEventListener).not.toHaveBeenCalledWith(appEventPrefix + eventName, trigger);
+            expect(console.warn).toHaveBeenCalledWith(jasmine.any(String));
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/events/deviceEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/events/deviceEvents.js b/lib/cordova-blackberry/framework/test/unit/lib/events/deviceEvents.js
new file mode 100644
index 0000000..2e55455
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/events/deviceEvents.js
@@ -0,0 +1,77 @@
+/*
+ * 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 _libDir = __dirname + "./../../../../lib/",
+    deviceEventPrefix = "device.",
+    deviceEvents;
+
+describe("lib/events/deviceEvents", function () {
+    beforeEach(function () {
+        GLOBAL.window = {
+            qnx: {
+                webplatform: {
+                    device: {
+                        addEventListener: jasmine.createSpy(),
+                        removeEventListener: jasmine.createSpy()
+                    }
+                }
+            }
+        };
+        deviceEvents = require(_libDir + "events/deviceEvents");
+    });
+
+    afterEach(function () {
+        delete GLOBAL.window;
+        deviceEvents = null;
+        delete require.cache[require.resolve(_libDir + "events/deviceEvents")];
+    });
+
+    describe("addEventListener", function () {
+        it("adds event name with application prepended", function () {
+            var eventName = "MostAwesomeEventEver",
+                trigger = function () {};
+            deviceEvents.addEventListener(eventName, trigger);
+            expect(window.qnx.webplatform.device.addEventListener).toHaveBeenCalledWith(deviceEventPrefix + eventName, trigger);
+        });
+
+        it("warns in the console if the eventName is falsey", function () {
+            var eventName = false,
+                trigger = function () {};
+            spyOn(console, "warn");
+            deviceEvents.addEventListener(eventName, trigger);
+            expect(window.qnx.webplatform.device.addEventListener).not.toHaveBeenCalledWith(deviceEventPrefix + eventName, trigger);
+            expect(console.warn).toHaveBeenCalledWith(jasmine.any(String));
+        });
+    });
+
+    describe("removeEventListener", function () {
+        it("adds event name with application prepended", function () {
+            var eventName = "MostAwesomeEventEver",
+                trigger = function () {};
+            deviceEvents.removeEventListener(eventName, trigger);
+            expect(window.qnx.webplatform.device.removeEventListener).toHaveBeenCalledWith(deviceEventPrefix + eventName, trigger);
+        });
+
+        it("warns in the console if the eventName is falsey", function () {
+            var eventName = false,
+                trigger = function () {};
+            spyOn(console, "warn");
+            deviceEvents.removeEventListener(eventName, trigger);
+            expect(window.qnx.webplatform.device.removeEventListener).not.toHaveBeenCalledWith(deviceEventPrefix + eventName, trigger);
+            expect(console.warn).toHaveBeenCalledWith(jasmine.any(String));
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/framework.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/framework.js b/lib/cordova-blackberry/framework/test/unit/lib/framework.js
new file mode 100644
index 0000000..312dd8b
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/framework.js
@@ -0,0 +1,429 @@
+/*
+ * 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 srcPath = __dirname + '/../../../lib/',
+    config = require(srcPath + "config"),
+    framework,
+    webview,
+    overlayWebView,
+    overlayWebViewObj,
+    controllerWebView,
+    Whitelist = require(srcPath + 'policy/whitelist').Whitelist,
+    mockedController,
+    mockedApplicationWindow,
+    mockedApplication,
+    mockedDevice,
+    mockedQnx,
+    mock_request = {
+        url: "http://www.dummy.com",
+        allow: jasmine.createSpy(),
+        deny: jasmine.createSpy()
+    };
+
+describe("framework", function () {
+    beforeEach(function () {
+        mockedController = {
+            id: 42,
+            enableCrossSiteXHR: undefined,
+            visible: undefined,
+            active: undefined,
+            zOrder: undefined,
+            url: undefined,
+            setGeometry: jasmine.createSpy(),
+            onNetworkResourceRequested: undefined,
+            destroy: jasmine.createSpy(),
+            executeJavaScript: jasmine.createSpy(),
+            windowGroup: undefined,
+            addEventListener: jasmine.createSpy(),
+            uiWebView: undefined,
+            onChildWindowOpen: undefined
+        };
+        mockedApplicationWindow = {
+            visible: undefined
+        };
+        mockedApplication = {
+            addEventListener: jasmine.createSpy(),
+            webInspectorPort : "1337",
+            invocation: {
+                invoke: jasmine.createSpy()
+            }
+        };
+        mockedDevice = {
+            getNetworkInterfaces : jasmine.createSpy()
+        };
+        mockedQnx = {
+            callExtensionMethod : function () {
+                return 42;
+            },
+            webplatform : {
+                getController : function () {
+                    return mockedController;
+                },
+                getApplication : function () {
+                    return mockedApplication;
+                },
+                getApplicationWindow : function () {
+                    return mockedApplicationWindow;
+                },
+                device : mockedDevice,
+                nativeCall: jasmine.createSpy("qnx.webplatform.nativeCall")
+            }
+        };
+        GLOBAL.window = {
+            qnx: mockedQnx
+        };
+        GLOBAL.qnx = mockedQnx;
+        GLOBAL.NamedNodeMap = function () {};
+
+        delete require.cache[require.resolve(srcPath + "webview")];
+        webview = require(srcPath + "webview");
+        delete require.cache[require.resolve(srcPath + "overlayWebView")];
+        overlayWebView = require(srcPath + "overlayWebView");
+        delete require.cache[require.resolve(srcPath + "controllerWebView")];
+        controllerWebView = require(srcPath + "controllerWebView");
+
+        spyOn(webview, "create").andCallFake(function (done) {
+            done();
+        });
+
+        spyOn(overlayWebView, "getWebViewObj").andCallFake(function () {
+            overlayWebViewObj = {
+                formcontrol: {
+                    subscribeTo: jasmine.createSpy()
+                }
+            };
+            return overlayWebViewObj;
+        });
+
+        spyOn(overlayWebView, "create").andCallFake(function (done) {
+            done();
+        });
+
+        spyOn(controllerWebView, "init");
+        spyOn(controllerWebView, "dispatchEvent");
+        spyOn(webview, "destroy");
+        spyOn(webview, "executeJavascript");
+        spyOn(webview, "setURL");
+        spyOn(webview, "setUIWebViewObj");
+        spyOn(webview, "addEventListener").andCallFake(function (eventName, callback) {
+            callback();
+        });
+        spyOn(webview, "removeEventListener");
+
+        spyOn(overlayWebView, "setURL");
+        spyOn(overlayWebView, "renderContextMenuFor");
+        spyOn(overlayWebView, "handleDialogFor");
+        spyOn(overlayWebView, "addEventListener").andCallFake(function (eventName, callback) {
+            callback();
+        });
+        spyOn(overlayWebView, "removeEventListener");
+        spyOn(overlayWebView, "bindAppWebViewToChildWebViewControls");
+
+        delete require.cache[require.resolve(srcPath + "framework")];
+        framework = require(srcPath + 'framework');
+    });
+
+    afterEach(function () {
+        delete GLOBAL.blackberry;
+        delete GLOBAL.window;
+        delete GLOBAL.qnx;
+        delete GLOBAL.NamedNodeMap;
+    });
+
+    it("can start a webview instance", function () {
+        framework.start();
+        expect(controllerWebView.init).toHaveBeenCalled();
+        expect(webview.create).toHaveBeenCalled();
+    });
+
+    it("on start passing callback and setting object parameters to create method of webview", function () {
+        framework.start();
+        expect(webview.create).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Object));
+    });
+
+    it("setting object should have debugEnabled to be defined", function () {
+        framework.start();
+        expect((webview.create.mostRecentCall.args)[1].debugEnabled).toBeDefined();
+    });
+
+    it("can start a webview instance with a url", function () {
+        var url = "http://www.google.com";
+        framework.start(url);
+        expect(webview.setURL).toHaveBeenCalledWith(url);
+    });
+
+    it("can stop a webview instance", function () {
+        framework.start();
+        framework.stop();
+        expect(webview.destroy).toHaveBeenCalled();
+    });
+
+    describe('creating the overlay webview', function () {
+        beforeEach(function () {
+            framework.start();
+        });
+        it('calls overlayWebView.create', function () {
+            expect(overlayWebView.create).toHaveBeenCalled();
+        });
+
+        it('sets the overlayWebView URL', function () {
+            expect(overlayWebView.setURL).toHaveBeenCalledWith("local:///chrome/ui.html");
+        });
+
+        it('calls renderContextMenuFor passing the webview', function () {
+            expect(overlayWebView.renderContextMenuFor).toHaveBeenCalledWith(webview);
+        });
+
+        it('calls handleDialogFor passing the webview', function () {
+            expect(overlayWebView.handleDialogFor).toHaveBeenCalledWith(webview);
+        });
+
+        it('dispatches the ui.init event on the controllerWebView', function () {
+            expect(controllerWebView.dispatchEvent).toHaveBeenCalledWith('ui.init', null);
+        });
+    });
+
+    describe('configuring webSecurity', function () {
+        var enableCrossSiteXHRSetter;
+
+        beforeEach(function () {
+            enableCrossSiteXHRSetter = jasmine.createSpy();
+            Object.defineProperty(webview, "enableCrossSiteXHR", {set: enableCrossSiteXHRSetter, configurable: true});
+        });
+
+        afterEach(function () {
+            delete webview.enableCrossSiteXHR;
+            delete require.cache[require.resolve(srcPath + "webview")];
+            webview = require(srcPath + "webview");
+        });
+
+        it('does not call enableCrossSiteXHR by default', function () {
+            expect(config.enableWebSecurity).toBe(true);
+            framework.start();
+
+            expect(enableCrossSiteXHRSetter).not.toHaveBeenCalledWith(true);
+        });
+
+        it('does enable crossSiteXHR when the config says too', function () {
+            delete require.cache[require.resolve(srcPath + "config")];
+            config = require(srcPath + 'config');
+            config.enableWebSecurity = false;
+
+            //reload config in framework
+            delete require.cache[require.resolve(srcPath + "framework")];
+            framework = require(srcPath + 'framework');
+
+            this.after(function () {
+                delete require.cache[require.resolve(srcPath + "config")];
+                config = require(srcPath + 'config');
+
+                delete require.cache[require.resolve(srcPath + "framework")];
+                framework = require(srcPath + 'framework');
+            });
+
+            expect(config.enableWebSecurity).toBe(false);
+            framework.start();
+
+            expect(enableCrossSiteXHRSetter).toHaveBeenCalledWith(true);
+        });
+    });
+
+    describe('configuring OpenChildWindow events', function () {
+        var onChildWindowOpenHandler;
+
+        beforeEach(function () {
+            Object.defineProperty(webview, "onChildWindowOpen", {set: function (input) {
+                onChildWindowOpenHandler = input;
+            }, configurable: true});
+        });
+
+        afterEach(function () {
+            delete webview.onChildWindowOpen;
+            delete require.cache[require.resolve(srcPath + "webview")];
+            webview = require(srcPath + "webview");
+        });
+
+        it('delegates to childWebViewControls on the overlay webview', function () {
+            config.enableChildWebView = true;
+
+            //reload config in framework
+            delete require.cache[require.resolve(srcPath + "framework")];
+            framework = require(srcPath + 'framework');
+
+            this.after(function () {
+                delete require.cache[require.resolve(srcPath + "config")];
+                config = require(srcPath + 'config');
+            });
+
+            framework.start();
+            expect(overlayWebView.bindAppWebViewToChildWebViewControls).toHaveBeenCalledWith(webview);
+            expect(webview.onChildWindowOpen).not.toBeDefined();
+        });
+
+        it('binds to OpenChildWindow and invokes the browser', function () {
+            config.enableChildWebView = false;
+
+            //reload config in framework
+            delete require.cache[require.resolve(srcPath + "framework")];
+            framework = require(srcPath + 'framework');
+
+            this.after(function () {
+                delete require.cache[require.resolve(srcPath + "config")];
+                config = require(srcPath + 'config');
+            });
+
+            framework.start();
+            expect(overlayWebView.bindAppWebViewToChildWebViewControls).not.toHaveBeenCalledWith(webview);
+            expect(onChildWindowOpenHandler).toEqual(jasmine.any(Function));
+            onChildWindowOpenHandler(JSON.stringify({url: 'http://www.google.com'}));
+            expect(mockedApplication.invocation.invoke).toHaveBeenCalledWith(
+                {uri: 'http://www.google.com', target: "sys.browser" }
+            );
+        });
+    });
+
+    describe('shows the webinspector dialog', function () {
+        it('show the webinspector dialog', function () {
+            var flag = false;
+            spyOn(overlayWebView, "showDialog");
+
+            window.qnx.webplatform.device.getNetworkInterfaces = function (callback) {
+                callback();
+                flag = true;
+            };
+            config.debugEnabled = true;
+            framework.start();
+            waitsFor(function () {
+                return flag;
+            });
+            runs(function () {
+                expect(overlayWebView.showDialog).toHaveBeenCalled();
+            });
+        });
+
+        it('show the webinspector dialog with the correct IP address', function () {
+            var flag = false,
+            messageObj;
+            spyOn(overlayWebView, "showDialog");
+
+            window.qnx.webplatform.device.getNetworkInterfaces = function (callback) {
+                var dummyData = {
+                    asix0i : null,
+                    bb0 : null,
+                    bptp0 : null,
+                    cellular0 : null,
+                    cellular1 : null,
+                    cellular2 : null,
+                    cellular3 : null,
+                    cellular4 : null,
+                    ecm0 : {
+                        connected : true,
+                        ipv4Address : "169.254.0.1",
+                        ipv6Address : "fe80::70aa:b2ff:fef9:b374",
+                        type : "usb"
+                    },
+                    ipsec0 : null,
+                    ipsec1 : null,
+                    lo0 : null,
+                    lo2 : null,
+                    nap0 : null,
+                    pan0 : null,
+                    pflog0 : null,
+                    ppp0 : null,
+                    rndis0 : null,
+                    smsc0 : null,
+                    tiw_drv0 : null,
+                    tiw_ibss0 : null,
+                    tiw_p2pdev0 : null,
+                    tiw_p2pgrp0 : null,
+                    tiw_sta0 : {
+                        connected : true,
+                        ipv4Address : "192.168.2.2",
+                        ipv6Address : "fe80::72aa:b2ff:fef9:b374",
+                        type : "wifi"
+                    },
+                    vlan0 : null,
+                    vpn0 : null
+                };
+                callback(dummyData);
+                flag = true;
+            };
+            config.debugEnabled = true;
+            framework.start();
+            waitsFor(function () {
+                return flag;
+            });
+            runs(function () {
+                messageObj = {
+                    title : "Web Inspector Enabled",
+                    htmlmessage : "\n ip4:    169.254.0.1:1337<br/> ip6:    fe80::70aa:b2ff:fef9:b374:1337",
+                    dialogType : "JavaScriptAlert"
+                };
+                expect(overlayWebView.showDialog).toHaveBeenCalledWith(messageObj);
+            });
+        });
+
+    });
+
+    describe('enabling form control', function () {
+        var originalConfigVal;
+
+        beforeEach(function () {
+            originalConfigVal = config.enableFormControl;
+        });
+
+        afterEach(function () {
+            config.enableFormControl = originalConfigVal;
+        });
+
+        it('subscribes webview to formcontrol', function () {
+            config.enableFormControl = true;
+            framework.start();
+            expect(overlayWebViewObj.formcontrol.subscribeTo).toHaveBeenCalledWith(webview);
+        });
+
+        it('does not subscribe webview to formcontrol is enableFormControl is false', function () {
+            config.enableFormControl = false;
+            framework.start();
+            expect(overlayWebViewObj.formcontrol.subscribeTo).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('enabling popup blocker', function () {
+        var originalConfigVal;
+
+        beforeEach(function () {
+            originalConfigVal = config.enablePopupBlocker;
+        });
+
+        afterEach(function () {
+            config.enablePopupBlocker = originalConfigVal;
+        });
+
+        it('does nothing when enablePopupBlocker is true', function () {
+            config.enablePopupBlocker = true;
+            framework.start();
+            expect(mockedQnx.webplatform.nativeCall).not.toHaveBeenCalledWith('webview.setBlockPopups', webview.id, false);
+        });
+
+        it('Disables popupblocker when enablePopupBlocker is false', function () {
+            config.enablePopupBlocker = false;
+            framework.start();
+            expect(mockedQnx.webplatform.nativeCall).toHaveBeenCalledWith('webview.setBlockPopups', webview.id, false);
+        });
+    });
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/overlayWebView.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/overlayWebView.js b/lib/cordova-blackberry/framework/test/unit/lib/overlayWebView.js
new file mode 100644
index 0000000..21150a9
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/overlayWebView.js
@@ -0,0 +1,187 @@
+/*
+ *  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.
+ */
+describe("Overlay Webview", function () {
+    var webview,
+        libPath = "./../../../",
+        mockedController,
+        mockedWebview,
+        mockedApplication;
+
+    beforeEach(function () {
+        webview = require(libPath + "lib/overlayWebView");
+        mockedWebview = {
+            id: 42,
+            enableCrossSiteXHR: undefined,
+            visible: undefined,
+            active: undefined,
+            zOrder: undefined,
+            url: undefined,
+            setGeometry: jasmine.createSpy(),
+            setApplicationOrientation: jasmine.createSpy(),
+            notifyApplicationOrientationDone: jasmine.createSpy(),
+            onContextMenuRequestEvent: undefined,
+            onNetworkResourceRequested: undefined,
+            destroy: jasmine.createSpy(),
+            executeJavaScript: jasmine.createSpy(),
+            windowGroup: undefined,
+            addEventListener: jasmine.createSpy(),
+            enableWebEventRedirect: jasmine.createSpy(),
+            notifyContextMenuCancelled: jasmine.createSpy(),
+            allowQnxObject: undefined,
+            allowRpc: undefined,
+            contextMenu: {
+                subscribeTo: jasmine.createSpy()
+            },
+            invocationlist: {
+                show: jasmine.createSpy()
+            }
+        };
+        mockedController = {
+            dispatchEvent : jasmine.createSpy(),
+            addEventListener : jasmine.createSpy()
+        };
+
+        mockedApplication = {
+            windowVisible: undefined
+        };
+        GLOBAL.qnx = {
+            callExtensionMethod: jasmine.createSpy(),
+            webplatform: {
+                getController: function () {
+                    return mockedController;
+                },
+                createUIWebView: function (createFunction) {
+                    runs(createFunction);
+                    return mockedWebview;
+                },
+                getApplication: function () {
+                    return mockedApplication;
+                }
+            }
+        };
+        GLOBAL.window = {
+            qnx: qnx
+        };
+        GLOBAL.screen = {
+            width : 1024,
+            height: 768
+        };
+    });
+
+    describe("create", function () {
+        it("sets up the visible webview", function () {
+            webview.create();
+            waits(1);
+            runs(function () {
+                expect(mockedWebview.visible).toEqual(true);
+                expect(mockedWebview.active).toEqual(true);
+                expect(mockedWebview.zOrder).toEqual(2);
+                expect(mockedWebview.setGeometry).toHaveBeenCalledWith(0, 0, screen.width, screen.height);
+                expect(mockedWebview.backgroundColor).toEqual(0x00FFFFFF);
+                expect(mockedWebview.sensitivity).toEqual("SensitivityTest");
+                expect(mockedWebview.allowQnxObject).toEqual(true);
+                expect(mockedWebview.allowRpc).toEqual(true);
+                expect(mockedController.dispatchEvent).toHaveBeenCalledWith("overlayWebView.initialized", jasmine.any(Array));
+            });
+        });
+
+        it("calls the ready function", function () {
+            var chuck = jasmine.createSpy();
+            webview.create(chuck);
+            waits(1);
+            runs(function () {
+                expect(chuck).toHaveBeenCalled();
+            });
+        });
+
+    });
+
+    describe("methods other than create", function () {
+
+        it("calls the underlying destroy", function () {
+            webview.create(mockedWebview);
+            webview.destroy();
+            expect(mockedWebview.destroy).toHaveBeenCalled();
+        });
+
+        it("sets the url property", function () {
+            var url = "http://AWESOMESAUCE.com";
+            webview.create(mockedWebview);
+            webview.setURL(url);
+            expect(mockedWebview.url).toEqual(url);
+        });
+
+        it("calls the underlying executeJavascript", function () {
+            var js = "var awesome='Jasmine BDD'";
+            webview.create(mockedWebview);
+            webview.executeJavascript(js);
+            expect(mockedWebview.executeJavaScript).toHaveBeenCalledWith(js);
+        });
+        it("calls the underlying windowGroup property", function () {
+            webview.create(mockedWebview);
+            expect(webview.windowGroup()).toEqual(mockedWebview.windowGroup);
+        });
+
+        it("can get the id for the webiew", function () {
+            webview.create();
+            expect(webview.id).toEqual(mockedWebview.id);
+        });
+
+        it("can set geometry", function () {
+            webview.create();
+            webview.setGeometry(0, 0, 100, 200);
+            expect(mockedWebview.setGeometry).toHaveBeenCalledWith(0, 0, 100, 200);
+        });
+
+        it("can set application orientation", function () {
+            webview.create();
+            webview.setApplicationOrientation(90);
+            expect(mockedWebview.setApplicationOrientation).toHaveBeenCalledWith(90);
+        });
+
+        it("can notifyApplicationOrientationDone", function () {
+            webview.create();
+            webview.notifyApplicationOrientationDone();
+            expect(mockedWebview.notifyApplicationOrientationDone).toHaveBeenCalled();
+        });
+
+        it("can notifyContextMenuCancelled", function () {
+            webview.create();
+            webview.notifyContextMenuCancelled();
+            expect(mockedWebview.notifyContextMenuCancelled).toHaveBeenCalled();
+        });
+
+        it("can render the ccm for another webview ", function () {
+            webview.create();
+            webview.renderContextMenuFor(webview);
+            expect(mockedWebview.contextMenu.subscribeTo).toHaveBeenCalledWith(webview);
+        });
+
+        it("It has a zOrder propety ", function () {
+            expect(webview.zOrder).toBeDefined();
+        });
+
+        it('proxies calls to invocationlist.show()', function () {
+            var request = {},
+                title = {},
+                success = function () {},
+                error = function () {};
+            webview.create();
+            webview.showInvocationList(request, title, success, error);
+            expect(mockedWebview.invocationlist.show).toHaveBeenCalledWith(request, title, success, error);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/plugins/default.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/plugins/default.js b/lib/cordova-blackberry/framework/test/unit/lib/plugins/default.js
new file mode 100644
index 0000000..349bfea
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/plugins/default.js
@@ -0,0 +1,154 @@
+/*
+ * 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 ROOT = "../../../../";
+
+describe("default plugin", function () {
+
+    var defaultPlugin = require(ROOT + 'lib/plugins/default'),
+        testExtension,
+        utils,
+        mockController,
+        mockApplication;
+
+    describe("when handling requests", function () {
+        var req, res, succ, fail, args;
+
+        beforeEach(function () {
+            req = {
+                origin: "http://www.origin.com",
+                params: {}
+            };
+            res = {
+                send: jasmine.createSpy()
+            };
+            succ = jasmine.createSpy("lib/plugin/default success");
+            fail = jasmine.createSpy("lib/plugin/default fail");
+            args = {};
+
+            GLOBAL.frameworkModules = ["plugin/blackberry.app/index.js"];
+
+            //All of this mocking is required for modules to load, DO NOT REMOVE
+            mockController = {
+                dispatchEvent: jasmine.createSpy()
+            };
+            mockApplication = {
+            };
+            GLOBAL.window = {
+                qnx: {
+                    webplatform: {
+                        getController: jasmine.createSpy().andReturn(mockController),
+                        getApplication: jasmine.createSpy().andReturn(mockApplication)
+                    }
+                }
+            };
+
+            testExtension = {
+                getReadOnlyFields: function () {}
+            };
+
+            delete require.cache[require.resolve(ROOT + "lib/utils")];
+            utils = require(ROOT + "lib/utils");
+            spyOn(utils, "loadModule").andCallFake(function (module) {
+                // on device, "plugin/blackberry.app/index.js" would exist since packager would
+                // name the extension folder with feature id in compilation time
+                if (module.indexOf("/plugin") !== -1) {
+                    return testExtension;
+                } else {
+                    return undefined;
+                }
+            });
+        });
+
+        afterEach(function () {
+            delete GLOBAL.frameworkModules;
+            delete GLOBAL.window;
+        });
+
+        it("returns 404 if the extension is not found", function () {
+            var ext = "NotAnExt",
+                errMsg = "Extension " + ext + " not found";
+
+            req.params.ext = ext;
+            spyOn(console, "warn");
+
+            defaultPlugin.exec(req, succ, fail, args);
+
+            expect(fail).toHaveBeenCalledWith(-1, errMsg, 404);
+            expect(console.warn).toHaveBeenCalledWith(errMsg);
+        });
+
+        it("returns 404 if the method is not found", function () {
+            req.params.ext = "blackberry.app";
+            req.params.method = "NotAMethod";
+            spyOn(console, "warn");
+
+            defaultPlugin.exec(req, succ, fail, args);
+
+            expect(fail).toHaveBeenCalledWith(-1, jasmine.any(String), 404);
+            expect(console.warn).toHaveBeenCalledWith("Method " + req.params.method + " for " + req.params.ext + " not found");
+        });
+
+        it("calls the method of the extension", function () {
+            var env = {"request": req, "response": res};
+
+            spyOn(testExtension, "getReadOnlyFields");
+
+            req.params.ext = "blackberry.app";
+            req.params.method = "getReadOnlyFields";
+
+            defaultPlugin.exec(req, succ, fail, args, env);
+
+            expect(testExtension.getReadOnlyFields).toHaveBeenCalledWith(succ, fail, args, env);
+        });
+
+        it("calls a multi-level method of the extension", function () {
+            var env = {"request": req, "response": res};
+
+            spyOn(testExtension, "getReadOnlyFields");
+            testExtension.getReadOnlyFields.a = {
+                b : {
+                    c : jasmine.createSpy()
+                }
+            };
+
+            req.params.ext = "blackberry.app";
+            req.params.method = "getReadOnlyFields/a/b/c";
+
+            defaultPlugin.exec(req, succ, fail, args, env);
+
+            expect(fail).wasNotCalled();
+            expect(testExtension.getReadOnlyFields.a.b.c).toHaveBeenCalledWith(succ, fail, args, env);
+        });
+
+        it("throws a 404 is a multi-level method is not found", function () {
+            var env = {"request": req, "response": res};
+
+            spyOn(console, "warn");
+            spyOn(testExtension, "getReadOnlyFields");
+            testExtension.getReadOnlyFields.a = {
+            };
+
+            req.params.ext = "blackberry.app";
+            req.params.method = "getReadOnlyFields/a/b/c";
+
+            defaultPlugin.exec(req, succ, fail, args, env);
+
+            expect(fail).toHaveBeenCalledWith(-1, jasmine.any(String), 404);
+            expect(console.warn).toHaveBeenCalledWith("Method " + req.params.method + " for " + req.params.ext + " not found");
+        });
+    });
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/plugins/event.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/plugins/event.js b/lib/cordova-blackberry/framework/test/unit/lib/plugins/event.js
new file mode 100644
index 0000000..ea92f1d
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/plugins/event.js
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+describe("event plugin", function () {
+
+    var ROOT = "./../../../../",
+        eventLib = require(ROOT + "lib/event"),
+        eventPlugin;
+
+    describe("once function", function () {
+        var args = {
+            eventName: encodeURIComponent(JSON.stringify("GRRRRR"))
+        };
+
+        it("calls success if no error", function () {
+            var success = jasmine.createSpy(),
+                fail = jasmine.createSpy(),
+                webview = {};
+
+            spyOn(eventLib, "add");
+            delete require.cache[require.resolve(ROOT + "lib/plugins/event")];
+            eventPlugin = require(ROOT + "lib/plugins/event");
+            this.after(function () {
+                delete require.cache[require.resolve(ROOT + "lib/plugins/event")];
+            });
+
+            eventPlugin.once(undefined, success, fail, args, {webview: webview});
+
+            expect(eventLib.add).toHaveBeenCalledWith(
+                {
+                    event: "GRRRRR",
+                    once: true
+                },
+                webview
+            );
+            expect(success).toHaveBeenCalled();
+            expect(fail).not.toHaveBeenCalledWith(-1, jasmine.any(String));
+        });
+
+        it("calls fail if there is an error", function () {
+            var success = jasmine.createSpy(),
+                fail = jasmine.createSpy(),
+                webview = {};
+
+            spyOn(eventLib, "add").andThrow("ERRRORZ");
+            delete require.cache[require.resolve(ROOT + "lib/plugins/event")];
+            eventPlugin = require(ROOT + "lib/plugins/event");
+            this.after(function () {
+                delete require.cache[require.resolve(ROOT + "lib/plugins/event")];
+            });
+
+            eventPlugin.once(undefined, success, fail, args, {webview: webview});
+
+            expect(eventLib.add).toHaveBeenCalledWith(
+                {
+                    event: "GRRRRR",
+                    once: true
+                },
+                webview
+            );
+            expect(success).not.toHaveBeenCalled();
+            expect(fail).toHaveBeenCalledWith(-1, jasmine.any(String));
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/88ad654c/lib/cordova-blackberry/framework/test/unit/lib/policy/webkitOriginAccess.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/framework/test/unit/lib/policy/webkitOriginAccess.js b/lib/cordova-blackberry/framework/test/unit/lib/policy/webkitOriginAccess.js
new file mode 100644
index 0000000..4a5ac8e
--- /dev/null
+++ b/lib/cordova-blackberry/framework/test/unit/lib/policy/webkitOriginAccess.js
@@ -0,0 +1,194 @@
+/*
+ *  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 LIB_PATH = __dirname + "/../../../../lib/",
+    utils = require(LIB_PATH + 'utils'),
+    webkitOriginAccess = require(LIB_PATH + "policy/webkitOriginAccess"),
+    LOCAL_URI = "local://",
+    FILE_URI = "file://",
+    WW_URI = utils.getURIPrefix(),
+    mockWebView;
+
+describe("lib/policy/webkitOriginAccess", function () {
+    beforeEach(function () {
+        mockWebView = {
+            addOriginAccessWhitelistEntry: jasmine.createSpy()
+        };
+    });
+
+    afterEach(function () {
+        mockWebView = undefined;
+        delete require.cache[require.resolve(LIB_PATH + "config")];
+        delete require.cache[require.resolve(LIB_PATH + "policy/webkitOriginAccess")];
+        webkitOriginAccess = require(LIB_PATH + "policy/webkitOriginAccess");
+    });
+
+    function mockConfig(mockAccessList, hasMultiAccess) {
+        delete require.cache[require.resolve(LIB_PATH + "config")];
+        delete require.cache[require.resolve(LIB_PATH + "policy/webkitOriginAccess")];
+        var config = require(LIB_PATH + "config");
+        config.accessList = mockAccessList;
+        config.hasMultiAccess = !!hasMultiAccess;
+        webkitOriginAccess = require(LIB_PATH + "policy/webkitOriginAccess");
+    }
+
+    describe("addWebview function", function () {
+
+        it("exists", function () {
+            expect(webkitOriginAccess.addWebView).toBeDefined();
+        });
+
+        it("sets up one time whitelisting", function () {
+            webkitOriginAccess.addWebView(mockWebView);
+
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, FILE_URI, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(FILE_URI, LOCAL_URI, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, WW_URI, true);
+        });
+
+        it("initializes the webview with whitelisting based on the config", function () {
+            var mockAccessList = [
+                {
+                    uri : "http://google.com",
+                    allowSubDomain : true,
+                    features : null
+                }
+            ];
+            mockConfig(mockAccessList);
+
+            webkitOriginAccess.addWebView(mockWebView);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, "http://google.com", true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith("http://google.com", LOCAL_URI, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith("http://google.com", WW_URI, true);
+        });
+
+        it("initializes the webview with whitelisting based on what domains have been added", function () {
+            var mockAccessList = [{
+                    uri : "http://google.com",
+                    allowSubDomain : true,
+                    features : null
+                }],
+                url = "http://www.rim.com";
+
+            mockConfig(mockAccessList, true);
+
+            webkitOriginAccess.addOriginAccess(url, true);
+
+            webkitOriginAccess.addWebView(mockWebView);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, url, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, LOCAL_URI, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, "http://google.com", true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith("http://google.com", url, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, WW_URI, true);
+        });
+
+        it("will not initialize twice", function () {
+            var origCallCount;
+
+            webkitOriginAccess.addWebView(mockWebView);
+            origCallCount = mockWebView.addOriginAccessWhitelistEntry.callCount;
+            webkitOriginAccess.addWebView(mockWebView);
+
+            expect(mockWebView.addOriginAccessWhitelistEntry.callCount).toEqual(origCallCount);
+        });
+
+    });
+
+    describe("addOriginAccess function", function () {
+        it("exists", function () {
+            expect(webkitOriginAccess.addOriginAccess).toBeDefined();
+        });
+
+        it("Treats falsey values as false", function () {
+            var url = "http://www.rim.com";
+
+            webkitOriginAccess.addWebView(mockWebView);
+            webkitOriginAccess.addOriginAccess(url);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, url, false);
+        });
+
+        it("Adds access for any non-local and non-file url", function () {
+            var url = "http://www.rim.com/grrr/arrg/blah.htm";
+
+            webkitOriginAccess.addWebView(mockWebView);
+            webkitOriginAccess.addOriginAccess(url);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, url, false);
+        });
+
+        //Because local:// is already a domain, the spy should not have no new calls
+        it("Local uris are treated as local://", function () {
+            var url = "local:///buy/local/beef/mmmmmmmmmmmmm/Steak.yum",
+                origCallCount;
+
+            webkitOriginAccess.addWebView(mockWebView);
+            webkitOriginAccess.addOriginAccess(url);
+            origCallCount = mockWebView.addOriginAccessWhitelistEntry.callCount;
+            webkitOriginAccess.addOriginAccess(url);
+            expect(mockWebView.addOriginAccessWhitelistEntry.callCount).toEqual(origCallCount);
+        });
+
+        it("File uris are treated as file://", function () {
+            var url = "file:///buy/local/beef/mmmmmmmmmmmmm/Steak.yum",
+                authority = "file://";
+
+            webkitOriginAccess.addWebView(mockWebView);
+            webkitOriginAccess.addOriginAccess(url);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, authority, false);
+        });
+
+        it("updates all managed webviews of the new domain access", function () {
+            var mockWebView2 = {
+                    addOriginAccessWhitelistEntry: jasmine.createSpy()
+                },
+                url = "http://www.rim.com";
+
+            webkitOriginAccess.addWebView(mockWebView);
+            webkitOriginAccess.addWebView(mockWebView2);
+
+            webkitOriginAccess.addOriginAccess(url, true);
+
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, url, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, LOCAL_URI, true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, WW_URI, true);
+            expect(mockWebView2.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(LOCAL_URI, url, true);
+            expect(mockWebView2.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, LOCAL_URI, true);
+            expect(mockWebView2.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, WW_URI, true);
+        });
+
+        it("updates all managed webviews when a new domain is added", function () {
+            var mockAccessList = [{
+                    uri : "http://google.com",
+                    allowSubDomain : true,
+                    features : null
+                }],
+                url = "http://www.rim.com";
+
+            mockConfig(mockAccessList, true);
+
+            webkitOriginAccess.addWebView(mockWebView);
+
+            expect(mockWebView.addOriginAccessWhitelistEntry).not.toHaveBeenCalledWith(url, "http://google.com", true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).not.toHaveBeenCalledWith("http://google.com", url, true);
+
+            webkitOriginAccess.addOriginAccess(url, true);
+
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith(url, "http://google.com", true);
+            expect(mockWebView.addOriginAccessWhitelistEntry).toHaveBeenCalledWith("http://google.com", url, true);
+        });
+
+    });
+
+});