You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by lo...@apache.org on 2013/05/07 17:24:22 UTC
[17/51] [partial] [BlackBerry10] Added support for new platform
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/policy/whitelist.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/policy/whitelist.js b/lib/cordova-blackberry/blackberry10/framework/lib/policy/whitelist.js
new file mode 100644
index 0000000..dcfbc3c
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/server.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/server.js b/lib/cordova-blackberry/blackberry10/framework/lib/server.js
new file mode 100644
index 0000000..15b95b0
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/utils.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/utils.js b/lib/cordova-blackberry/blackberry10/framework/lib/utils.js
new file mode 100644
index 0000000..4ab008a
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/webkitEvent.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/webkitEvent.js b/lib/cordova-blackberry/blackberry10/framework/lib/webkitEvent.js
new file mode 100644
index 0000000..0f4bef7
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/webkitHandlers/networkResourceRequested.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/webkitHandlers/networkResourceRequested.js b/lib/cordova-blackberry/blackberry10/framework/lib/webkitHandlers/networkResourceRequested.js
new file mode 100644
index 0000000..759c8bd
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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);
+ }
+};
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/6831bed4/lib/cordova-blackberry/blackberry10/framework/lib/webview.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/lib/webview.js b/lib/cordova-blackberry/blackberry10/framework/lib/webview.js
new file mode 100644
index 0000000..495dfbe
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/config.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/config.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/config.js
new file mode 100644
index 0000000..64e8f7e
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/controllerWebView.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/controllerWebView.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/controllerWebView.js
new file mode 100644
index 0000000..003d276
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/event.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/event.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/event.js
new file mode 100644
index 0000000..3d3e7fe
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/applicationEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/applicationEvents.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/applicationEvents.js
new file mode 100644
index 0000000..81fa2e1
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/deviceEvents.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/deviceEvents.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/events/deviceEvents.js
new file mode 100644
index 0000000..2e55455
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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/6831bed4/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/framework.js
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/framework.js b/lib/cordova-blackberry/blackberry10/framework/test/unit/lib/framework.js
new file mode 100644
index 0000000..312dd8b
--- /dev/null
+++ b/lib/cordova-blackberry/blackberry10/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);
+ });
+ });
+
+});