(function () { 
/*
                                Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   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.

-------------------------------------------------------
Copyright 2011 Research In Motion Limited.

Contributors:
        Brent Lintner (blintner@rim.com)
        Dan Silivestru (dsilivestru@rim.com)
        Gord Tanner (gtanner@rim.com)
        Nino D'Aversa (ndaversa@rim.com)
        Nukul Bhasin (nbhasin@rim.com)

-------------------------------------------------------
--> Kudos to third party awesomeness:

* jWorkflow *

http://github.com/tinyhippos/jWorkflow/

The MIT License
http://www.opensource.org/licenses/mit-license.php
Copyright (c) 2010 all contributors:
Gord Tanner

-------------------------------------------------------
* Math.uuid.js (v1.4) *

http://www.broofa.com
mailto:robert@broofa.com

Copyright (c) 2010 Robert Kieffer
Dual licensed under the MIT and GPL licenses.

-------------------------------------------------------


*/
/**
 * almond 0.0.3 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/jrburke/almond for details
 */
/*jslint strict: false, plusplus: false */
/*global setTimeout: false */

var requirejs, require, define;
(function (undef) {

    var defined = {},
        waiting = {},
        aps = [].slice,
        main, req;

    if (typeof define === "function") {
        //If a define is already in play via another AMD loader,
        //do not overwrite.
        return;
    }

    /**
     * Given a relative module name, like ./something, normalize it to
     * a real name that can be mapped to a path.
     * @param {String} name the relative name
     * @param {String} baseName a real name that the name arg is relative
     * to.
     * @returns {String} normalized name
     */
    function normalize(name, baseName) {
        //Adjust any relative paths.
        if (name && name.charAt(0) === ".") {
            //If have a base name, try to normalize against it,
            //otherwise, assume it is a top-level require that will
            //be relative to baseUrl in the end.
            if (baseName) {
                //Convert baseName to array, and lop off the last part,
                //so that . matches that "directory" and not name of the baseName's
                //module. For instance, baseName of "one/two/three", maps to
                //"one/two/three.js", but we want the directory, "one/two" for
                //this normalization.
                baseName = baseName.split("/");
                baseName = baseName.slice(0, baseName.length - 1);

                name = baseName.concat(name.split("/"));

                //start trimDots
                var i, part;
                for (i = 0; (part = name[i]); i++) {
                    if (part === ".") {
                        name.splice(i, 1);
                        i -= 1;
                    } else if (part === "..") {
                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {
                            //End of the line. Keep at least one non-dot
                            //path segment at the front so it can be mapped
                            //correctly to disk. Otherwise, there is likely
                            //no path mapping for a path starting with '..'.
                            //This can still fail, but catches the most reasonable
                            //uses of ..
                            break;
                        } else if (i > 0) {
                            name.splice(i - 1, 2);
                            i -= 2;
                        }
                    }
                }
                //end trimDots

                name = name.join("/");
            }
        }
        return name;
    }

    function makeRequire(relName, forceSync) {
        return function () {
            //A version of a require function that passes a moduleName
            //value for items that may need to
            //look up paths relative to the moduleName
            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
        };
    }

    function makeNormalize(relName) {
        return function (name) {
            return normalize(name, relName);
        };
    }

    function makeLoad(depName) {
        return function (value) {
            defined[depName] = value;
        };
    }

    function callDep(name) {
        if (waiting.hasOwnProperty(name)) {
            var args = waiting[name];
            delete waiting[name];
            main.apply(undef, args);
        }
        return defined[name];
    }

    /**
     * Makes a name map, normalizing the name, and using a plugin
     * for normalization if necessary. Grabs a ref to plugin
     * too, as an optimization.
     */
    function makeMap(name, relName) {
        var prefix, plugin,
            index = name.indexOf('!');

        if (index !== -1) {
            prefix = normalize(name.slice(0, index), relName);
            name = name.slice(index + 1);
            plugin = callDep(prefix);

            //Normalize according
            if (plugin && plugin.normalize) {
                name = plugin.normalize(name, makeNormalize(relName));
            } else {
                name = normalize(name, relName);
            }
        } else {
            name = normalize(name, relName);
        }

        //Using ridiculous property names for space reasons
        return {
            f: prefix ? prefix + '!' + name : name, //fullName
            n: name,
            p: plugin
        };
    }

    main = function (name, deps, callback, relName) {
        var args = [],
            usingExports,
            cjsModule, depName, i, ret, map;

        //Use name if no relName
        if (!relName) {
            relName = name;
        }

        //Call the callback to define the module, if necessary.
        if (typeof callback === 'function') {

            //Default to require, exports, module if no deps if
            //the factory arg has any arguments specified.
            if (!deps.length && callback.length) {
                deps = ['require', 'exports', 'module'];
            }

            //Pull out the defined dependencies and pass the ordered
            //values to the callback.
            for (i = 0; i < deps.length; i++) {
                map = makeMap(deps[i], relName);
                depName = map.f;

                //Fast path CommonJS standard dependencies.
                if (depName === "require") {
                    args[i] = makeRequire(name);
                } else if (depName === "exports") {
                    //CommonJS module spec 1.1
                    args[i] = defined[name] = {};
                    usingExports = true;
                } else if (depName === "module") {
                    //CommonJS module spec 1.1
                    cjsModule = args[i] = {
                        id: name,
                        uri: '',
                        exports: defined[name]
                    };
                } else if (defined.hasOwnProperty(depName) || waiting.hasOwnProperty(depName)) {
                    args[i] = callDep(depName);
                } else if (map.p) {
                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
                    args[i] = defined[depName];
                } else {
                    throw name + ' missing ' + depName;
                }
            }

            ret = callback.apply(defined[name], args);

            if (name) {
                //If setting exports via "module" is in play,
                //favor that over return value and exports. After that,
                //favor a non-undefined return value over exports use.
                if (cjsModule && cjsModule.exports !== undef) {
                    defined[name] = cjsModule.exports;
                } else if (!usingExports) {
                    //Use the return value from the function.
                    defined[name] = ret;
                }
            }
        } else if (name) {
            //May just be an object definition for the module. Only
            //worry about defining if have a module name.
            defined[name] = callback;
        }
    };

    requirejs = req = function (deps, callback, relName, forceSync) {
        if (typeof deps === "string") {

            //Just return the module wanted. In this scenario, the
            //deps arg is the module name, and second arg (if passed)
            //is just the relName.
            //Normalize module name, if it contains . or ..
            return callDep(makeMap(deps, callback).f);
        } else if (!deps.splice) {
            //deps is a config object, not an array.
            //Drop the config stuff on the ground.
            if (callback.splice) {
                //callback is an array, which means it is a dependency list.
                //Adjust args if there are dependencies
                deps = callback;
                callback = arguments[2];
            } else {
                deps = [];
            }
        }

        //Simulate async callback;
        if (forceSync) {
            main(undef, deps, callback, relName);
        } else {
            setTimeout(function () {
                main(undef, deps, callback, relName);
            }, 15);
        }

        return req;
    };

    /**
     * Just drops the config on the floor, but returns req in case
     * the config return value is used.
     */
    req.config = function () {
        return req;
    };

    /**
     * Export require as a global, but only if it does not already exist.
     */
    if (!require) {
        require = req;
    }

    define = function (name, deps, callback) {

        //This module may not have dependencies
        if (!deps.splice) {
            //deps is not an array, so probably means
            //an object literal or factory function for
            //the value. Adjust args.
            callback = deps;
            deps = [];
        }

        if (define.unordered) {
            waiting[name] = [name, deps, callback];
        } else {
            main(name, deps, callback);
        }
    };

    define.amd = {
        jQuery: true
    };
}());

define('pps', function (require, exports, module) {
/*
* 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.
*/

/*jshint es5:true */

var pps,
    globalId = 0,
    ppsConnections = {};

function generateId() {
    var id = globalId++;
    if (!window.isFinite(id)) {
        globalId = 0;
        id = 0;
    }
    return id;
}

pps = {
    // PPS Modes
    PPSMode: { FULL: 0, DELTA: 1, SERVER: 2, RAW: 3 },
    // File mode constants for use with the open() function
    // WRONLY is fastest
    // CREATE can be or-ed with RDONLY, WRONLY, or RDWR (e.g. open("/pps/someppsobject", FileMode.CREATE|FileMode.WRONLY))
    FileMode: { RDONLY: 0, WRONLY: 1, RDWR: 2, CREATE: 256 },

    create: function (ppsPath, ppsMode) {
        var _id = generateId(),
            _path = ppsPath,
            _mode = ppsMode,
            _data,
            _returnObj;

        function isActive() {
            return ppsConnections.hasOwnProperty(_id);
        }

        function deactivate() {
            delete ppsConnections[_id];
        }

        function open(fileMode, options) {
            var obj = JSON.parse(qnx.callExtensionMethod('pps.open', _id, _path, _mode, fileMode, options));
            if (obj.result) {
                ppsConnections[_id] = this;
                _data = obj.data;
                return true;
            }
            return false;
        }

        function write(data) {
            if (isActive()) {
                qnx.callExtensionMethod('pps.write', _id, JSON.stringify(data));
            }
        }

        function close() {
            if (isActive()) {
                qnx.callExtensionMethod('pps.close', _id);
            }
        }

        _returnObj = {
            open : open,
            write : write,
            close : close,

            /**
             * @description Callback to be fired when the PPS object is first read after open() is called.
             * @type {function}
             */
            onFirstReadComplete: undefined,

            /**
             * @desription Callback fired when new data has changed in the PPS that you have open()
             * @type {function}
             */
            onNewData: undefined,

            onOpenFailed: function (message) {
                console.log('PPS Connection - open failed: ' + message);
            },
            onWriteFailed: function (message) {
                console.log('PPS Connection - write failed: ' + message);
            },
            onClosed : deactivate
        };

        _returnObj.__defineGetter__('data', function () {
            return _data;
        });

        _returnObj.__defineGetter__('path', function () {
            return _path;
        });

        return _returnObj;
    },

    onEvent: function (id, type, data) {
        if (!type || !ppsConnections.hasOwnProperty(id)) {
            return;
        }

        var ppsConnection = ppsConnections[id],
            eventHandlerName = 'on' + type;
        if (ppsConnection.hasOwnProperty(eventHandlerName) && ppsConnection[eventHandlerName]) {
            if (type === 'FirstReadComplete' || type === 'NewData') {
                data = JSON.parse(data);
                ppsConnection._data = data;
            }
            ppsConnection[eventHandlerName](data);
        }
    }
};

module.exports = pps;

});

define('utils', function (require, exports, module) {
/*
 * 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.
 */
/**#nocode+*/

var _self;

_self = {
    inNode: function () {
        return !!require.resolve;
    },

    getQnxNamespace: function () {
        return _self.inNode() ? null : qnx;
    },

    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;
    },

    // Check if a url is from a local protocal
    isLocalUrl: function (url) {
        if (url && url.indexOf('local:///') !== -1) {
            return true;
        }
        return false;
    }
};

module.exports = _self;

/**#nocode-*/

});

define('events', function (require, exports, module) {
/*
 *  Copyright 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.
 *
 *  NOTE: Taken from the Ripple-UI project
 *        https://github.com/blackberry/Ripple-UI/
 *
 *  MODIFICATIONS
 *      - renamed 'on' apis/methods to 'emit'
 *      - removed getEventSubscribers/eventHasSubscriber methods
 *      - remove usage of ripple's exception/utils modules
 *
 */
/* The following metaTag is added because this module would not be public */
/**#nocode+*/

var _listeners = {},
    propertyMatcher = new RegExp("^Property(.*)Event$");

function enableWebEvent(id, eventType, enable) {
    var matches = propertyMatcher.exec(eventType),
        command = matches ? "webview.setPropertyChangedEventEnabled" : "webview.setWebEventEnabled",
        property = matches ? matches[1] : eventType;
    qnx.callExtensionMethod(command, id, property, enable);
}

function listenersFor(id, type, create) {
    var result = _listeners[id] || [];

    if (!id) {
        throw "id must be truthy";
    }
    if (!type) {
        throw "type must be truthy";
    }

    result = result[type];

    if (!result && create) {
        _listeners[id] = _listeners[id] || [];
        _listeners[id][type] = []; //Cannot exist
        result = _listeners[id][type]; //Pass by reference
    }

    return result;
}

function on(id, type, listener, scope, once) {
    var listeners = listenersFor(id, type, true);
    listeners.push({
        func: listener,
        scope: scope,
        once: !!once
    });
    enableWebEvent(id, type, true);
}

function emit(listener, args, sync) {
    try {
        if (sync) {
            return listener.func.apply(listener.scope, args);
        } else {
            setTimeout(function () {
                listener.func.apply(listener.scope, args);
            }, 1);
        }
    } catch (e) {
        console.error(e && e.stack || e);
    }
}

function removeEventListener(id, type, targetListener, scope, once) {
    var listeners = listenersFor(id, type),
        i;

    if (listeners) {
        for (i = 0; i < listeners.length; i++) {
            if (listeners[i].func === targetListener) {
                listeners.splice(i, 1); // delete
                if (listeners.length === 0) {
                    enableWebEvent(id, type, false);
                }
                break;
            }
        }
    }
}

module.exports = {
    on: function (id, type, listener, scope) {
        on(id, type, listener, scope);
    },

    once : function (id, type, listener, scope) {
        on(id, type, listener, scope, true);
    },

    //The emit function has 3 required params and 1 optional
    //The options function has two subparameters
    //options.sync means whether to emit synchronously (default false)
    //options.shouldReturn means
    emit: function (id, type, args, options) {
        var listeners = listenersFor(id, type),
            returnValue,
            sync,
            shouldReturn;
        args = args || [];
        options = options || {};
        sync = !!options.sync || false;
        shouldReturn = !!options.shouldReturn || false;
        if (listeners) {
            listeners.some(function (listener) {
                returnValue = emit(listener, args, sync);
                if (shouldReturn && returnValue) {
                    return true;
                }
                returnValue = null;
                return false;
            });

            if (shouldReturn && returnValue) {
                return returnValue;
            }

            //This array must exist or we wouldn't hit this block
            _listeners[id][type] = listeners.filter(function (listener) {
                return !listener.once;
            });
        }
    },

    removeEventListener: removeEventListener,

    clear: function (id) {
        if (id) {
            delete _listeners[id];
        }
    },

    receiveAllPropertyChangedEvents: function (id, enabled) {
        qnx.callExtensionMethod("webview.setAllPropertyChangedEventsEnabled", id, enabled);
    }
};
/**#nocode-*/

});

define('chrome', function (require, exports, module) {
/*
 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
 */
var self;

self = {
    id: 1,
};

module.exports = self;

});

define('invocation', function (require, exports, module) {
/*
* Copyright 2011-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 invocation,
    globalId = 0,
    messageCallbacks = {},
    viewers = {},
    cardResizeId,
    utils = require('./utils');

function generateId() {
    var id = globalId++;
    if (!window.isFinite(id)) {
        globalId = 0;
        id = 0;
    }
    return id;
}

invocation = {

    LAUNCH: 0,
    INVOKE: 1,
    VIEWER: 2,
    CARD: 3,

    INVOKE_NO_TARGET_ERROR: 'INVOKE_NO_TARGET_ERROR',
    INVOKE_BAD_REQUEST_ERROR: 'INVOKE_BAD_REQUEST_ERROR',
    INVOKE_INTERNAL_ERROR: 'INVOKE_INTERNAL_ERROR',
    INVOKE_TARGET_ERROR: 'INVOKE_TARGET_ERROR',
    INVOKE_TARGET_NOT_OWNED_ERROR: 'INVOKE_TARGET_NOT_OWNED_ERROR',

    QUERY_TARGETS_INVALID_ARGUMENT: 'invalid_argument',
    QUERY_TARGETS_RESPONSE_TOO_LARGE: 'response_too_large',
    QUERY_TARGETS_SERVER_ERROR: 'server_error',

    TARGET_TYPE_MASK_APPLICATION: 1,
    TARGET_TYPE_MASK_CARD: 2,
    TARGET_TYPE_MASK_VIEWER: 4,
    TARGET_TYPE_MASK_SERVICE: 8,

    ACTION_TYPE_ALL: 'ALL',
    ACTION_TYPE_MENU: 'MENU',

    PERIMETER_TYPE_PERSONAL: 'personal',
    PERIMETER_TYPE_ENTERPRISE: 'enterprise',

    FILE_TRANSFER_PRESERVE : 'PRESERVE',
    FILE_TRANSFER_COPY_RO : 'COPY_RO',
    FILE_TRANSFER_COPY_RW : 'COPY_RW',
    FILE_TRANSFER_LINK : 'LINK',

    CARD_EDGE_TOP: 'top_up',
    CARD_EDGE_BOTTOM: 'bottom_up',
    CARD_EDGE_LEFT: 'left_up',
    CARD_EDGE_RIGHT: 'right_up',

    CARD_ORIENTATION_PORTRAIT: 'portrait',
    CARD_ORIENTATION_LANDSCAPE: 'landscape',

    CARD_PEEK_TYPE_CONTENT: 'content',
    CARD_PEEK_TYPE_ROOT: 'root',

    getStartupMode: function () {
        var application = window.qnx.webplatform.getApplication(),
            mode,
            uri = application.getEnv('uri');
        if (uri === 'invoke://localhost') {
            mode = application.getEnv('MODE');
            if (mode === 'card') {
                return invocation.CARD;
            } else if (mode === 'view') {
                return invocation.VIEWER;
            } else {
                return invocation.INVOKE;
            }
        } else {
            return invocation.LAUNCH;
        }
    },

    getRequest: function () {
        return qnx.callExtensionMethod('invocation.invokeRequest');
    },

    invoke: function (request, callback) {
        var id = generateId(),
            baseDir = window.qnx.webplatform.getApplication().getEnv("HOME") + "";

        // If the request contains a local URL, let's parse it out
        if (utils.isLocalUrl(request.uri)) {
            request.uri = "file:///" + baseDir.replace(/^\/*/, '') + "/../app/native/" + request.uri.replace(/local:\/\/\//, '');
        }

        if (callback) {
            messageCallbacks[id] = callback;
        }
        qnx.callExtensionMethod('invocation.invoke', id, JSON.stringify(request));
    },

    invokeViewer: function (request, callback) {
        var id = generateId(),
            viewerId;

        if (callback) {
            messageCallbacks[id] = callback;
        }
        viewerId = 'viewer' + id;
        request.winid = viewerId;
        qnx.callExtensionMethod('invocation.invokeViewer', id, viewerId, JSON.stringify(request));
    },

    queryTargets: function (request, callback) {
        var id = generateId();
        messageCallbacks[id] = callback;
        qnx.callExtensionMethod('invocation.queryTargets', id, JSON.stringify(request));
    },

    cardResized: function () {
        if (cardResizeId) {
            qnx.callExtensionMethod('invocation.cardResize', cardResizeId);
        }
    },

    cardPeek: function (peekType) {
        qnx.callExtensionMethod('invocation.cardPeek', peekType);
    },

    closeChildCard: function () {
        qnx.callExtensionMethod('invocation.cardChildClose');
    },

    sendCardDone: function (request) {
        qnx.callExtensionMethod('invocation.cardClose', JSON.stringify(request));
    },

    getInvokeTargetFilters: function (target, callback) {
        var id = generateId(),
            request;

        messageCallbacks[id] = callback;
        request = {
            target: target
        };
        qnx.callExtensionMethod('invocation.getInvokeTargetFilters', id, JSON.stringify(request));
    },

    setInvokeTargetFilters: function (request, callback) {
        var id = generateId();
        if (callback) {
            messageCallbacks[id] = callback;
        }
        qnx.callExtensionMethod('invocation.setInvokeTargetFilters', id, JSON.stringify(request));
    },

    onInvoked: function (request) {
        qnx.webplatform.getController().dispatchEvent('invocation.invoked', [request]);
    },

    onInvokeResponse: function (id, error, response) {
        var callback = messageCallbacks[id];
        if (callback) {
            delete messageCallbacks[id];
            callback(error, response ? JSON.parse(response) : null);
        }
    },

    onInvokeViewerResponse: function (id, error) {
        if (error) {
            var callback = messageCallbacks[id];
            delete messageCallbacks[id];
            if (callback) {
                callback(error);
            }
        }
    },

    onQueryTargetsResponse: function (id, error, response) {
        var callback = messageCallbacks[id];
        if (callback) {
            delete messageCallbacks[id];
            callback(error, response ? JSON.parse(response) : null);
        }
    },

    onViewerCreate: function (id, viewerId) {
        var callback = messageCallbacks[id],
            viewer;
        delete messageCallbacks[id];
        viewer = {
            viewerId: viewerId,
            relayCallbacks: {},

            close: function () {
                qnx.callExtensionMethod('invocation.closeViewer', this.viewerId);
            },

            receive: function (id, message) {
                var name = message.msg;

                if (name === 'viewerCloseRequest') {
                    this.close();
                    if (this.hasOwnProperty('onClose')) {
                        this.onClose();
                    }
                } else if (name === 'viewerCancelRequest') {
                    this.close();
                    if (this.hasOwnProperty('onCancel')) {
                        this.onCancel();
                    }
                } else if (this.hasOwnProperty('onReceive')) {
                    this.onReceive(id, message.msg, message.dat);
                }
            },

            receiveResponse: function (id, response) {
                var callback = this.relayCallbacks[id];
                delete this.relayCallbacks[id];
                if (callback) {
                    callback(response.name, response.dat);
                }
            },

            setSize: function (width, height) {
                var message = {
                    msg: 'resizeReqeust',
                    data: {
                        width: width,
                        height: height
                    }
                };
                this.send(JSON.stringify(message));
            },

            setPosition: function (x, y) {
                qnx.callExtensionMethod('invocation.setViewerPosition', this.viewerId, x, y);
            },

            setVisibility: function (visibility) {
                qnx.callExtensionMethod('invocation.setViewerVisibility', this.viewerId, visibility);
            },

            setZOrder: function (zOrder) {
                qnx.callExtensionMethod('invocation.setViewerZOrder', this.viewerId, zOrder);
            },

            send: function (message, callback) {
                var id = generateId();
                if (callback) {
                    this.relayCallbacks[id] = callback;
                }
                message.winid = this.viewerId;
                qnx.callExtensionMethod('invocation.viewerRelay', id, message);
            },

            update: function () {
                qnx.callExtensionMethod('applicationWindow.flushContext');
            },
        };
        viewers[viewer.viewerId] = viewer;
        callback(null, viewer);
    },

    onViewerRelay: function (id, message) {
        var obj = JSON.parse(message),
            viewer = viewers[obj.winId];
        if (viewer) {
            viewer.receive(id, obj);
        }
    },

    onViewerRelayResponse: function (id, response) {
        var obj = JSON.parse(response),
            viewer = viewers[obj.winId];
        if (viewer) {
            viewer.receiveResponse(id, obj);
        }
    },

    onViewerStopped: function (viewerId) {
        delete viewers[viewerId];
    },

    onCardResize: function (id, request) {
        var values = request.split(','),
            resizeRequest = {
                width: values[0],
                height: values[1],
                orientation: values[2],
                edge: values[3]
            };

        //Handles id internally. Save it and use later when sending cardResize response.
        cardResizeId = id;
        qnx.webplatform.getController().dispatchEvent('invocation.cardResize', [resizeRequest]);
    },

    onCardStartPeek: function (peekType) {
        qnx.webplatform.getController().dispatchEvent('invocation.cardPeekStarted', [peekType]);
    },

    onCardEndPeek: function () {
        qnx.webplatform.getController().dispatchEvent('invocation.cardPeekEnded');
    },

    onCardChildClosed: function (reason, type, data) {
        var request = {
            reason: reason || "",
            type: type || "",
            data: data || ""
        };
        qnx.webplatform.getController().dispatchEvent('invocation.childCardClosed', [request]);
    },

    onCardClosed: function (reason, type, data) {
        var request = {
            reason: reason || "",
            type: type || "",
            data: data || ""
        };
        qnx.webplatform.getController().dispatchEvent('invocation.cardClosed', [request]);
    },

    onGetInvokeTargetFiltersResponse: function (id, error, response) {
        var callback = messageCallbacks[id];
        if (callback) {
            delete messageCallbacks[id];
            callback(error, response ? JSON.parse(response) : null);
        }
    },

    onSetInvokeTargetFiltersResponse: function (id, error, response) {
        var callback = messageCallbacks[id];
        if (callback) {
            delete messageCallbacks[id];
            callback(error, response ? JSON.parse(response) : null);
        }
    },
};

module.exports = invocation;

});

define('rpc', function (require, exports, module) {
/*
 *  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.
 *
 */
/* The following metaTag is added because this module would not be public */
/**#nocode+*/

var rpc, 
    _published = {},
    _pendingCallbacks = {},
    lastId = 0,
    hasBeenInit;

function publish(webviewId, name, callback, options) {
    options = options || {};
   
    // Initialize WebView ID if it does not yet exist
    if (!_published[webviewId]) {
        _published[webviewId] = {};
    }

    _published[webviewId][name] = {
        callback: callback,
        scope: options.scope,
        once: options.once 
    };
}

function unpublish(webviewId, name) { 
    delete _published[webviewId][name];
}

function execute(targetFunc, args, sync, callback) {
    try {
        if (sync) {
            return targetFunc.callback.apply(targetFunc.scope, args);
        } else {
            setTimeout(function () {
                var params = [args, callback];
                targetFunc.callback.apply(targetFunc.scope, params);
            }, 1);
        }
    } catch (e) {
        console.error(e && e.stack || e);
    }
}

function init() {
    var controller = window.qnx.webplatform.getController();
    controller.addEventListener('JavaScriptCallback', function (value, sourceWebViewId) {
        var args = eval(JSON.parse(value)['args']),
            command = args[0],
            name = args[1],
            functionArgs = eval(args[2]), //TODO: Better way to convert string to array
            callbackId = args[3];
        
        // Handle only the webplatform.rpc commands    
        if (command === 'webplatform.rpc') {
            rpc.runPublishedFunction(controller.id, name, functionArgs, false, function (result) {
                var params = callbackId,
                    callbackCode;
                if (result) { 
                    params +=  ", " + JSON.stringify(result);
                }
                callbackCode = "qnx.webplatform.getController().runRemoteExecCallback(" + params + ")";
                qnx.callExtensionMethod('webview.executeJavaScript', sourceWebViewId, callbackCode, "NormalWorld");                  
            });
        }
    });
}

rpc = {
    // For controller webview
    publish: function (webviewId, name, callback, options) {
        if (!hasBeenInit) {
            hasBeenInit = true;
            init();
        }
        // Error checking
        if (!webviewId) { 
            throw "WebView ID is invalid"; //TODO: i18n
        } 
        if (!name) {
            throw "Function name is invalid"; // TODO: i18n
        }
        publish(webviewId, name, callback, options);
    },

    unpublish: function (webviewId, name) {
        if (!name) {
            throw "Function name is invalid"; // TODO: i18n
        }
        unpublish(webviewId, name);
    },

    // runPublishedFunction has 3 required params and 2 optional
    runPublishedFunction: function (webviewId, name, args, sync, callback) {
        var targetFunc = _published[webviewId][name],
            returnVal;
        
        args = args || [];
        if (!targetFunc) {
            throw "WebView with ID " + webviewId + " has not published a function named '" + name + "'"; //TODO: i18n
        } 

        returnVal = execute(targetFunc, args, sync, callback);

        // Remove stored callback if intended to run only once    
        if (targetFunc.once) {
            delete _published[webviewId][name];
        }

        if (sync) {
            return returnVal;
        }
    },

    clear: function (webviewId) {
        if (webviewId) {
            delete _published[webviewId];
        }
    },

    // For the client webviews
    remoteExec: function (webviewId, name, args, callback) {
        
        _pendingCallbacks[lastId] = callback;
        
        // Use webplatform.rpc to send values to the controller
        // Will show up as a 'JavaScriptCallback' event in the controller
        qnx.callExtensionMethod('webplatform.rpc', name, JSON.stringify(args),  lastId++);
    },

    runRemoteExecCallback: function (callbackId, args) {
        var params = args ? JSON.parse(args) : undefined;
        _pendingCallbacks[callbackId](params);
        delete _pendingCallbacks[callbackId];
    }
};

module.exports = rpc;
/**#nocode-*/

});

define('webEventRouter', function (require, exports, module) {
/*
* 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.
*/
/* The following metaTag is added because this module would not be public */
/**#nocode+*/
var webEventRouter,
    _redirects = {};

webEventRouter = {
    enableRedirect: function (eventId, sourceWebViewId, targetWebViewId, returnVal) {
        _redirects[eventId] = _redirects[eventId] || {};
        _redirects[eventId][sourceWebViewId] = {
            targetWebViewId: targetWebViewId,
            returnVal: returnVal
        };
    },

    disableRedirect: function (eventId, sourceWebViewId) {
        delete _redirects[eventId][sourceWebViewId];
    },

    route: function (eventId, sourceWebViewId) {
        var returnObj;
        if (_redirects[eventId]) {
            returnObj = _redirects[eventId][sourceWebViewId]; 
        }  
        return returnObj ? returnObj : {targetWebViewId: sourceWebViewId}; 
    }
};

module.exports = webEventRouter;
/**#nocode-*/

});

define('chrome/events/application', function (require, exports, module) {
/*
* Copyright 2011-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.
*/

function getAngle(edge) {
    switch (edge) {
    case "right_up":
        return 90;
    case "left_up":
        return 270;
    case "bottom_up":
        return 180;
    default:
        return 0;
    }
}

var application = { 
    onExit: function () {
        qnx.webplatform.getController().dispatchEvent("application.exit");
    },
    onFontInfoChange: function (family, size) {
        qnx.webplatform.getController().dispatchEvent('application.fontchanged', [family, size]);
    },
    onKeyboardOpening: function () {
        qnx.webplatform.getController().dispatchEvent("application.keyboardOpening");
    },
    onKeyboardOpened: function () {
        qnx.webplatform.getController().dispatchEvent("application.keyboardOpened");
    },
    onKeyboardClosing: function () {
        qnx.webplatform.getController().dispatchEvent("application.keyboardClosing");
    },
    onKeyboardClosed: function () {
        qnx.webplatform.getController().dispatchEvent("application.keyboardClosed");
    },
    onKeyboardPosition: function (yPosition) {
        qnx.webplatform.getController().dispatchEvent("application.keyboardPosition", [yPosition]);
    },
    onLanguageChange: function () {
        qnx.webplatform.getController().dispatchEvent("application.systemLanguageChange");
    },
    onLowMemory: function () {
        qnx.webplatform.getController().dispatchEvent("application.lowMemory");
    },
    onRegionChange: function () {
        qnx.webplatform.getController().dispatchEvent("application.systemRegionChange");
    },
    onRotate: function (orientation, edge) {
        var screenWidth = screen.width,
            screenHeight = screen.height,

            angle = getAngle(edge),
            angleChange = angle - window.orientation,
            width = screenWidth,
            height = screenHeight;

        if (angleChange % 180) {
            width = screenHeight;
            height = screenWidth;
        }

        qnx.webplatform.getController().dispatchEvent("application.rotate", [width, height, angle], true);
    },
    onRotateCheck: function (orientation, edge) {
        return true;
    },
    onRotateDone: function (edge) {
        var angle = getAngle(edge);
        qnx.webplatform.getController().dispatchEvent("application.rotateDone", [angle]);
    },
    onPropertyViewportEvent: function () {
        qnx.webplatform.getController().dispatchEvent("application.propertyViewportEvent");
    },
    onSwipeDown: function () {
        qnx.webplatform.getController().dispatchEvent("application.swipedown");
    },
    onWindowActive: function () {
        qnx.webplatform.getController().dispatchEvent("application.resume");
    },
    onWindowInactive: function () {
        qnx.webplatform.getController().dispatchEvent("application.pause");
    },
    onWindowState: function (state) {
        var windowState = "AppActivationStateInactive";
        if (state === "fullscreen") {
            windowState = "AppActivationStateActive";
        } else if (state === "thumbnail") {
            windowState = "AppActivationStateStandby";
        }

        qnx.callExtensionMethod("webview.setApplicationActivationState", qnx.webplatform.getController().id, [windowState]);
    }
};

module.exports = application;

});

define('cards/capture', function (require, exports, module) {
/*
 * Copyright 2012 Research In Motion Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

module.exports = {
      // The camera can be invoked in three modes.
    MODE_PHOTO: 'photo',
    MODE_VIDEO: 'video',
    MODE_FULL: 'full',

    open: function (mode, done, cancel, invokeCallback) {

        var application = window.qnx.webplatform.getApplication(),
            callback;

        callback =  function (info) {
            if (info.reason === "save") {
                done(info.data);
            } else if (info.reason === "done" || info.reason === "close") {
                cancel(info.reason);
            }

            application.invocation.removeEventListener("childCardClosed", callback);
        };
        application.invocation.addEventListener("childCardClosed", callback);

        application.invocation.invoke({
            action: "bb.action.CAPTURE",
            target: "sys.camera.card",
            data: window.btoa(mode)
        }, function (error) {
            invokeCallback(error);
        });

    }
};


});

define('cards/file', function (require, exports, module) {
/*
 * 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.
*/
function ppsEncodeObject(obj) {
    var data = '',
        name,
        value;
    for (name in obj) {
        data += name + ':';
        value = obj[name];
        if (typeof value === 'string') {
            data += ':' + value;
        } else if (typeof value === 'number') {
            data += 'n:' + value;
        } else if (typeof value === 'boolean') {
            data += 'b:' + value;
        } else if (typeof value === 'object') {
            data += 'json:' + JSON.stringify(value);
        }
        data += '\n';
    }
    return data;
}

module.exports = {

    MODE_PICKER: 'Picker',
    MODE_SAVER: 'Saver',
    MODE_PICKER_MULTIPLE: 'PickerMultiple',
    MODE_SAVER_MULTIPLE: 'SaverMultiple',

    VIEWER_MODE_LIST: 'ListView',
    VIEWER_MODE_GRID: 'GridView',

    SORT_BY_NAME: 'Name',
    SORT_BY_DATE: 'Date',
    SORT_BY_SUFFIX: 'Suffix',
    SORT_BY_SIZE: 'Size',

    SORT_ORDER_ASCENDING: 'Ascending',
    SORT_ORDER_DESCENDING: 'Descending',

    TYPE_PICTURE: 'picture',
    TYPE_DOCUMENT: 'document',
    TYPE_MUSIC: 'music',
    TYPE_VIDEO: 'video',
    TYPE_OTHER: 'other',

    open: function (details, done, cancel, invokeCallback) {
        var application = window.qnx.webplatform.getApplication(),
            data = {
                Mode: details.mode,
                Title: details.title,
                ViewMode: details.viewMode,
                SortBy: details.sortBy,
                SortOrder: details.sortOrder,
                ImageCrop: details.imageCrop,
                AllowOverwrite: details.allowOverwrite,
                Type: details.type ? details.type.join(',') : [],
                DefaultType: details.defaultType,
                Filter: details.filter ? details.filter.join(';') : [],
                Directory: details.directory ? details.directory.join(',') : [],
                DefaultFileNames: details.defaultSaveFileNames ? details.defaultSaveFileNames.join(',') : []
            },
            encodedData,
            callback;

        callback =  function (info) {
            if (info.reason === "save") {
                var result = info.data,
                    path,
                    arrayResult = [];
                if (info && info.data && info.data.match("^dat:json")) { //strip off dat:json
                    result = info.data.slice(9);
                }
                result = JSON.parse(result);

                result.forEach(function (file) {
                    path = file.uri;
                    if (path.match("^file:///")) { //strip off file://
                        path = path.slice(7);
                    }
                    if (path.match("file:")) { //strip off file:
                        path = "";
                    }
                    if (path !== "")
                        arrayResult.push(path);
                });

                done(arrayResult);
            } else if (info.reason === "cancel") {
                cancel(info.reason);
            }

            application.invocation.removeEventListener("childCardClosed", callback);
        };
        application.invocation.addEventListener("childCardClosed", callback);

        encodedData = ppsEncodeObject(data);

        application.invocation.invoke({
            action: "bb.action.OPEN",
            target: "sys.filepicker.target",
            data: window.btoa(encodedData)
        }, function (error) {
            invokeCallback(error);
        });

    }
};


});

define('defaultHandlers/onChooseFile', function (require, exports, module) {
/*
 * Copyright 2012 Research In Motion Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

module.exports = {
    handle: function (paramsString, baton) {
        var capture,
        file,
        details,
        captureMode,
        params = JSON.parse(paramsString);

        baton.take();
        if (params.capture === 'camera' || params.capture === 'camcorder') {
            capture = require('./../cards/capture');
            captureMode = params.capture === 'camera' ? capture.MODE_PHOTO : capture.MODE_VIDEO;

            capture.open(captureMode, function (path) {
                baton.pass('{"setPreventDefault": true, "setFileChosen": "' + encodeURIComponent(path) + '"}');
            },
            function () {
                baton.pass('{"setPreventDefault": true}');
            },
            function (error) {
                if (error) {
                    baton.pass('{"setPreventDefault": true}');
                }
            });
        } else {
            file = require('./../cards/file');
            details = {
                mode: file.MODE_PICKER
            };

            file.open(details, function (filepaths) {
                baton.pass('{"setPreventDefault": true, "setFileChosen": "' + encodeURIComponent(filepaths[0]) + '"}');
            },
            function () {
                baton.pass('{"setPreventDefault": true}');
            },
            function (error) {
                if (error) {
                    baton.pass('{"setPreventDefault": true}');
                }
            });
        }
    }
};

});

define('cards/bbmInviteDownload', function (require, exports, module) {
/*
* Copyright 2012 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module.exports = {
    open : function (details, done, cancel, callback) {
        var application = qnx.webplatform.getApplication();
        
        application.invocation.invoke({
            target : 'com.rim.bb.bbm.composer',
            type : 'bbm/sp',
            action : 'bbm.sp.action.DOWNLOAD_INVITE',
            data : window.btoa(JSON.stringify({
                "contactPicker" : {
                    "gid" : details.gid,
                    "payload" : {
                        "DownloadContactPicker" : {}
                    }
                }
            }))
        }, callback);
    }
};

});

define('Application', function (require, exports, module) {
/*
* Copyright 2011-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 Application,
    invocation = require("./invocation"),
    invocationEvts = ["Invoked", "cardResize", "cardPeekStarted", "cardPeekEnded", "childCardClosed", "cardClosed"],
    validEvents = [
        "application.state",
        "application.pause",
        "application.resume",
        "application.swipedown",
        "application.exit",
        "application.fontchanged",
        "application.lowMemory",
        "application.rotate",
        "application.rotateDone",
        "application.keyboardOpening",
        "application.keyboardOpened",
        "application.keyboardClosing",
        "application.keyboardClosed",
        "application.keyboardPosition",
        "application.propertyViewportEvent",
        "application.systemLanguageChange",
        "application.systemRegionChange"
    ];

/**
 * @class A javascript abstraction of the application
 * @property {Boolean} visible Whether the application window is visible or not
 */
Application = function () {
    this.__defineGetter__("windowVisible", function () {
        return !!qnx.callExtensionMethod("applicationWindow.isVisible");
    });

    this.__defineSetter__("windowVisible", function (newVisibility) {
        qnx.callExtensionMethod("applicationWindow.setVisible", !!newVisibility);
    });

    /**
     * @description Returns the system region
     */
    this.__defineGetter__("systemRegion", function () {
        return qnx.callExtensionMethod('application.systemRegion');
    });

    /**
     * @description Gets the port for Web Inspector.
     */
    this.__defineGetter__("webInspectorPort", function () {
        return qnx.callExtensionMethod("webInspector.port");
    });

    /**
     * @description Gets an environment variable.
     * @param {String} name The name of the environment variable to get.
     */
    this.getEnv = function (name) {
        return qnx.callExtensionMethod('application.getenv', name);
    };

    /**
     * @description Sets an environment variable.
     * @param {String} name The name of the environment variable to set.
     * @param {String} value The value of the environment variable to set.
     */
    this.setEnv = function (name, value) {
        return qnx.callExtensionMethod('application.setenv', name, value);
    };

    /**
     * @description Removes an environment variable.
     * @param {String} name The name of the environment variable to unset.
     */
    this.unsetEnv = function (name) {
        return qnx.callExtensionMethod('application.unsetenv', name);
    };

    /**
     *@description Notifies the application that rotation handling is complete.
     */
    this.notifyRotateComplete = function () {
        qnx.callExtensionMethod('application.notifyRotateComplete');
    };

    /**
     *@description Returns system font family.
     */
    this.getSystemFontFamily = function () {
        return qnx.callExtensionMethod('application.systemFontFamily');
    };

    /**
     *@description Returns system font size in pixels.
     */
    this.getSystemFontSize = function () {
        return parseInt(qnx.callExtensionMethod('application.systemFontSize'), 10);
    };

    /**
     *@description Exits the application.
     */
    this.exit = function () {
        qnx.callExtensionMethod('application.exit');
    };

    /**
     * @description Adds a listener for event.
     * @param {String} evt The event to listen for. It will only handle valid events.
     * @param {callback} handler The function to be invoked when the event occurs
     */
    this.addEventListener = function (evt, handler) {
        if (validEvents.indexOf(evt) >= 0) {
            qnx.webplatform.getController().addEventListener(evt, handler);
        }
    };

    /**
     * @description Removes a listener for an event.
     * @param {String} evt The event to remove listener for. It will only handle valid events.
     * @param {callback} handler The function to be invoked when the event occurs
     */
    this.removeEventListener = function (evt, handler) {
        if (validEvents.indexOf(evt) >= 0) {
            qnx.webplatform.getController().removeEventListener(evt, handler);
        }
    };

    /**
     * @description Sets orientation at application level.
     * @param {Number} angle Angle of desired orientation.
     */
    this.setWindowOrientation = function (angle) {
        qnx.callExtensionMethod('applicationWindow.setOrientation', angle);
    };
};

Application.prototype.invocation = {

    /**
     * @description Constant value for when invocation was performed using navigator launch.
     */
    LAUNCH: invocation.LAUNCH,
    /**
     * @description Constant value for when invocation was performed using invoke from another app in application mode.
     */
    INVOKE: invocation.INVOKE,

    /**
     * @description Constant value for when invocation was performed using invoke from another app in viewer mode.
     */
    VIEWER: invocation.VIEWER,

    /**
     * @description Constant value for when invocation was performed using invoke from another app in card mode.
     */
    CARD: invocation.CARD,

    /**
     * @description Constant value representing the target type mask for applications.
     */
    TARGET_TYPE_MASK_APPLICATION: invocation.TARGET_TYPE_MASK_APPLICATION,

    /**
     * @description Constant value representing the target type mask for cards.
     */
    TARGET_TYPE_MASK_CARD: invocation.TARGET_TYPE_MASK_CARD,

    /**
     * @description Constant value representing the target type mask for viewers.
     */
    TARGET_TYPE_MASK_VIEWER: invocation.TARGET_TYPE_MASK_VIEWER,

    /**
     * @description Constant value representing the target type mask for services.
     */
    TARGET_TYPE_MASK_SERVICE: invocation.TARGET_TYPE_MASK_SERVICE,

    /**
     * @description Constant value for invocation to include all the action types
     */
    ACTION_TYPE_ALL: invocation.ACTION_TYPE_ALL,

    /**
     * @description Constant value for invocation to define the discoverable actions that can be presented in menus
     */
    ACTION_TYPE_MENU: invocation.ACTION_TYPE_MENU,

    /**
     * @description Costant value for invocation that tells the box to box to preserve the URI as is
     * and do not alter it to a file protocol. NO box-2-box logic is applied
     */
    FILE_TRANSFER_PRESERVE : invocation.FILE_TRANSFER_PRESERVE,

    /**
     * @description Costant value for invocation that tells the box to box to copy the file to the receivers inbox
     * with the Read and Other only
     */
    FILE_TRANSFER_COPY_RO : invocation.FILE_TRANSFER_COPY_RO,

    /**
     * @description Costant value for invocation that tells the box to box to copy the file to the receivers inbox
     * with the Read and Write privileges
     */
    FILE_TRANSFER_COPY_RW : invocation.FILE_TRANSFER_COPY_RW,

    /**
     * @description Constant value for invocation box to box transfer permissions allows a link to be created to a file
     * from the sender to the receivers inbox
     */
    FILE_TRANSFER_LINK : invocation.FILE_TRANSFER_LINK,

    /**
     * @description Sends an invoke request to the invocation framework.
     * @param {Object} request The invoke request
     * @param {callback} callback The function to be triggered when the response comes back
     */
    invoke: invocation.invoke,

    /**
     * @description Sends an invokeViewer request to the invocation framework.
     * @param {Object} request The invokeViewer request
     * @param {callback} callback The function to be triggered when the response comes back
     */
    invokeViewer: invocation.invokeViewer,

    /**
     * @description Sends a queryTargets request to the invocation framework.
     * @param {Object} request The queryTargets request
     * @param {callback} callback The function to be triggered when the response comes back
     */
    queryTargets: invocation.queryTargets,

    /**
     * @description Start-up mode of the application.
     */
    getStartupMode: invocation.getStartupMode,

    /**
     * @description get the invocation request.
     */
    getRequest: invocation.getRequest,

    /**
     * @description Sends cardResize request to invocation framework.
     */
    cardResized: invocation.cardResized,

    /**
     * @description Sends cardPeek request to invocation framework. The card peek request allows the card to specify the type of peek to be performed.
     * @param {String} peekType Describes the type of peek to be performed.
     *                          This can be a peek to the content of the parent or a peek to the content of the root.
     *                          The root is the first parent in a chain of cards
     */
    cardPeek: invocation.cardPeek,

    /**
     * @description Sends cardChildClose request to invocation framework to request that the stack above it be closed.
     */
    closeChildCard: invocation.closeChildCard,

    /**
     * @description When a card completes its task it may request closure by sending a cardClose request to invocation framework.
     * @param {Object} request The card close request.
     */
    sendCardDone: invocation.sendCardDone,

    /**
     * @description Retrieves the invoke target filters associated with the specified target. The specified target MUST be hosted by the calling process.
     * @param {String} target The name of the target whose filters are requested.
     * @param {callback} callback The function to be triggered when the response comes back.
     */
    getInvokeTargetFilters: invocation.getInvokeTargetFilters,

    /**
     * @description Replaces the filters associated with the specified target with the set provided in the request. This request can only be made by a process hosting the specified target.
     * @param {Object} request The request contains new filters.
     * @param {callback} callback The function to be triggered when the response comes back.
     */
    setInvokeTargetFilters: invocation.setInvokeTargetFilters,

    /**#@+
    * @param {String} evt The invocation event to listen for.<b> Only the following events can be listened to or the method will fail silently.</b><br/>
    * Can be one of
        'Invoked',
        'cardResize',
        'cardPeekStarted',
        'cardPeekEnded',
        'childCardClosed',
        'cardClosed'
    **/

    /**
     * @description Adds a listener for an invocation event.
     * @param {String} evt The invocation event to listen for, which can be one of event defined in the invocationEvts array. It will not handle any other events.
     * @param {callback} handler The function to be invoked when the event occurs
     */
    addEventListener: function (evt, handler) {
        if (invocationEvts.indexOf(evt) >= 0) {
            var fullEvtName = "invocation." + evt.charAt(0).toLowerCase() + evt.slice(1);
            qnx.webplatform.getController().addEventListener(fullEvtName, handler);
        }
    },

    /**
     * @description Removes a listener for an invocation event.
     * @param {String} evt The invocation event to remove listener for, which can be one of event defined in the invocationEvts array. It will not handle any other events.
     * @param {callback} handler The function to be invoked when the event occurs
     */
    removeEventListener: function (evt, handler) {
        if (invocationEvts.indexOf(evt) >= 0) {
            var fullEvtName = "invocation." + evt.charAt(0).toLowerCase() + evt.slice(1);
            qnx.webplatform.getController().removeEventListener(fullEvtName, handler);
        }
    }
};

Application.prototype.cards = {
    filePicker: require("./cards/file"),
    camera: require("./cards/capture"),
    bbm: {
        inviteToDownload : require('./cards/bbmInviteDownload')
    }
};

module.exports = Application;

});

define('chrome/internal', function (require, exports, module) {
/*
 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
 */
var events = require('../events'),
    chrome = require("../chrome"),
    application = require("../chrome/events/application"),
    invocation = require("../invocation"),
    webEventRouter = require("../webEventRouter"),
    pps =  require('../pps'),
    sendEvents = [
       /**
        * @memberOf WebView
        * @event
        * @name onJavaScriptWindowObjectCleared
        */
        'JavaScriptWindowObjectCleared',
       /**
        * @memberOf WebView
        * @event
        * @name onLocationChanging
        */
        'LocationChanging',
       /**
        * @memberOf WebView
        * @event
        * @name onContextMenuRequestEvent
        */
        'ContextMenuRequestEvent',
       /**
        * @memberOf WebView
        * @event
        * @name onPropertyCurrentContextEvent
        */
        'PropertyCurrentContextEvent',
        /**
         * @memberOf WebView
         * @event
         * @name onUnknownProtocol
         */
        'UnknownProtocol',

        /**
         * @memberOf WebView
         * @event
         * @name onDialogRequested
         */
        'DialogRequested',
        /**
         * @memberOf WebView
         * @event
         * @name onChooseFile
         */
        'ChooseFile',

        /**
         * @memberOf WebView
         * @event
         * @name onSSLHandshakingFailed
         */
        'SSLHandshakingFailed',

        /**
         * @memberOf WebView
         * @event
         * @name onGeolocationPermissionRequest
         */
        'GeolocationPermissionRequest',

        /**
         * @memberOf WebView
         * @event
         * @name onNotificationPermissionRequest
         */
        'NotificationPermissionRequest',

        /**
         * @memberOf WebView
         * @event
         * @name onNotificationPermissionCheck
         */
        'NotificationPermissionCheck'
    ],
   /**
    * @memberOf WebView
    * @event
    * @name onNetworkResourceRequested
    * @description This event handler will fire whenever a network resource is requested. The handler should return an action indicating what should be done (one of ALLOW, DENY, or SUBSTITUTE).
    */
    networkEvent = 'NetworkResourceRequested',
    plainEvents = [
        'ContentRendered',
        'ContextMenuCancelEvent',
        'Created',
        'Destroyed',
        'DocumentLoadCommitted',
        'DocumentLoaded',
        'DocumentLoadFinished',
        'JavaScriptCallback',
        'JavaScriptResult',
        'LocationChange',
        'NetworkError',
        'PropertyActiveEvent',
        'PropertyBackgroundColorEvent',
        'PropertyCanGoBackEvent',
        'PropertyCanGoForwardEvent',
        'PropertyCertificateInfoEvent',
        'PropertyContentRectangleEvent',
        'PropertyEnableWebInspectorEvent',
        'PropertyEncryptionInfoEvent',
        'PropertyFaviconEvent',
        'PropertyHistoryListEvent',
        'PropertyHistoryPositionEvent',
        'PropertyJavaScriptInterruptTimeoutEvent',
        'PropertyLoadProgressEvent',
        'PropertyLocationEvent',
        'PropertyOriginalLocationEvent',
        'PropertyScaleEvent',
        'PropertyScrollPositionEvent',
        'PropertySecureTypeEvent',
        'PropertyStatusEvent',
        'PropertyTitleEvent',
        'PropertyTooltipEvent',
        'PropertyVisibleEvent',
        'PropertyWebInspectorPortEvent',
        'PropertyViewportEvent',
        'PropertyZOrderEvent',
        'QNXWebDestroyedEvent',
        'NotificationShow',
        'NotificationCancel'
    ];


function createBaton(eventId) {
    var taken = false;

    function take() {
        if (!taken) {
            taken = true;
            qnx.callExtensionMethod('eventLoop.delayEvent', eventId);
        }
    }
    function pass(options) {
        if (taken) {
            taken = false;
            qnx.callExtensionMethod('eventLoop.resumeEvent', eventId, options);
        }
    }
    function drop(errorMsg, options) {
        if (taken) {
            taken = false;
            qnx.callExtensionMethod('eventLoop.resumeEvent', eventId, options);
            qnx.callExtensionMethod("webview.log", chrome.id, errorMsg);
        }
    }

    return {
        take: take,
        pass: pass,
        drop: drop
    };

}

module.exports = {
    sendEvents: sendEvents,
    plainEvents: plainEvents,
    enableWebEventRedirect: webEventRouter.enableRedirect,
    disableWebEventRedirect: webEventRouter.disableRedirect,
    application: {
        onWindowState: application.onWindowState,
        onWindowActive: application.onWindowActive,
        onWindowInactive: application.onWindowInactive,
        onSwipeDown: application.onSwipeDown,
        onExit: application.onExit,
        onFontInfoChange: application.onFontInfoChange,
        onLowMemory: application.onLowMemory,
        onRotate: application.onRotate,
        onRotateDone: application.onRotateDone,
        notifyRotateComplete: application.notifyRotateComplete,
        onKeyboardOpening: application.onKeyboardOpening,
        onKeyboardOpened: application.onKeyboardOpened,
        onKeyboardClosing: application.onKeyboardClosing,
        onKeyboardClosed: application.onKeyboardClosed,
        onKeyboardPosition: application.onKeyboardPosition
    },
    invocation: {
        onInvoked: invocation.onInvoked,
        onInvokeResponse: invocation.onInvokeResponse,
        onInvokeViewerResponse: invocation.onInvokeViewerResponse,
        onQueryTargetsResponse: invocation.onQueryTargetsResponse,
        onViewerCreate: invocation.onViewerCreate,
        onViewerRelay: invocation.onViewerRelay,
        onViewerRelayResponse: invocation.onViewerRelayResponse,
        onViewerStopped: invocation.onViewerStopped,
        onCardResize: invocation.onCardResize,
        onCardStartPeek: invocation.onCardStartPeek,
        onCardEndPeek: invocation.onCardEndPeek,
        onCardChildClosed: invocation.onCardChildClosed,
        onCardClosed: invocation.onCardClosed,
        onGetInvokeTargetFiltersResponse: invocation.onGetInvokeTargetFiltersResponse,
        onSetInvokeTargetFiltersResponse: invocation.onSetInvokeTargetFiltersResponse
    },
    pps: {
        onEvent: pps.onEvent
    },
    webEvent: function (webviewId, eventName, eventArgs, eventId) {

        // Redirect web events if needed
        var routingObj = webEventRouter.route(eventName, webviewId),
            originalWebViewId = webviewId;
        webviewId = routingObj.targetWebViewId;
        eventArgs = originalWebViewId === webviewId ? [eventArgs] : [eventArgs, originalWebViewId];

        //There are two different types of events we need to handle
        //Plain QNXWebEvents that are a one way pub sub model
        //SendEvents that require a return value and thus need to be handled synchronously
        if (eventName === networkEvent || sendEvents.indexOf(eventName) !== -1) {
            if (eventId !== -1) {
                eventArgs.push(createBaton(eventId));
            }
            return events.emit(webviewId, eventName, eventArgs, {sync: true, shouldReturn: true});
        } else if (plainEvents.indexOf(eventName) !== -1) {
            events.emit(webviewId, eventName, eventArgs);
        }
        else {
            qnx.callExtensionMethod("webview.log", chrome.id, "Unknown Event: " + eventName + ":" + eventArgs);
        }
    }
};

});

define('WebView', function (require, exports, module) {
/*
* 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 WebView,
    events = require('./events'),
    chrome = require('./chrome'),
    internal = require('./chrome/internal'),
    rpc = require('./rpc');

/**
 * @class A javascript abstraction of the underlying webkit webview
 * @property {Number} id The id of the webview. READ ONLY
 * @property {Number} windowGroup The windowGroup of the webview. READ ONLY
 * @property {Boolean} visible Whether the webview is currently visible
 * @property {Boolean} active Whether the webview is currently active
 * @property {Number} zOrder The zOrder of the webview
 * @property {String} url The fully qualified url currently loaded into the webview
 * @property {String} originalLocation The original location of a webview. READ ONLY
 * @property {Boolean} enableCrossSiteXHR Sets whether CrossSiteXHR is enabled or disabled for the webview
 * @property {Boolean} enableWebInspector Sets whether WebInspector is enabled or disabled for the webview
 * @property {Boolean} allowQnxObject Sets whether the WebView is allowed to access the qnx object
 * @property {Boolean} pluginsEnabled Sets whether plugins are enabled for the WebView
 */
///////////////////////////////////
//Webviews can be created using options.
//options.WebViewId specifies the webview id
//options.onCreate should be the onCreate function
//options.processType specifies the the process type of the webview
///////////////////////////////////
function WebView(options) {

    var _windowGroup = qnx.callExtensionMethod("webview.applicationWindowGroup", chrome.id),
        //Either should be the input id or create a new webview
        _processType = (options && typeof options.processType === 'number') ? options.processType : 0,
        _defaultHandlers = (options && options.defaultHandlers) ? options.defaultHandlers : [],
        _id = (options && options.WebViewId) ? options.WebViewId : parseInt(qnx.callExtensionMethod('webview.create', _windowGroup, _processType), 10),
        _listeners = {},
        _qnxObjectEnabled = false,
        that = this;

    // Disable all PropertyChangedEvents by default
    events.receiveAllPropertyChangedEvents(_id, false);

    if (options && options.onCreate) {
        events.on(_id, "Created", options.onCreate);
    }

    this.__defineGetter__("id", function () {
        return _id;
    });

    this.__defineGetter__("windowGroup", function () {
        return _windowGroup;
    });

    this.__defineGetter__("visible", function () {
        return !!qnx.callExtensionMethod("webview.isVisible", this.id);
    });

    this.__defineSetter__("visible", function (newVisibility) {
        qnx.callExtensionMethod("webview.setVisible", this.id, !!newVisibility);
    });

    this.__defineGetter__("pluginsEnabled", function () {
        return !!qnx.callExtensionMethod('webview.isEnablePlugins', this.id);
    });

    this.__defineSetter__("pluginsEnabled", function (pluginsEnabled) {
        qnx.callExtensionMethod('webview.setEnablePlugins', this.id, pluginsEnabled);
    });

    this.__defineGetter__("active", function () {
        return qnx.callExtensionMethod("webview.isActive", this.id);
    });

    this.__defineSetter__("backgroundColor", function (backgroundColor) {
        qnx.callExtensionMethod("webview.setBackgroundColor", this.id, backgroundColor);
    });

    this.__defineGetter__("backgroundColor", function (backgroundColor) {
        return qnx.callExtensionMethod("webview.backgroundColor", this.id);
    });

    this.__defineSetter__("devicePixelRatio", function (pixelRatio) {
        qnx.callExtensionMethod("webview.setDevicePixelRatio", this.id, pixelRatio);
    });

    this.__defineGetter__("devicePixelRatio", function () {
        return qnx.callExtensionMethod("webview.devicePixelRatio", this.id);
    });

    this.__defineSetter__("sensitivity", function (sensitivity) {
        qnx.callExtensionMethod("webview.setSensitivity", this.id, sensitivity);
    });

    this.__defineGetter__("sensitivity", function (sensitivity) {
        return qnx.callExtensionMethod("webview.sensitivity", this.id);
    });

    this.__defineSetter__("active", function (newActivity) {
        qnx.callExtensionMethod("webview.setActive", this.id, !!newActivity);
    });

    this.__defineGetter__("zOrder", function () {
        return qnx.callExtensionMethod("webview.zOrder", this.id);
    });

    this.__defineSetter__("zOrder", function (newZOrder) {
        qnx.callExtensionMethod("webview.setZOrder", this.id, parseInt(newZOrder, 10));
    });

    this.__defineGetter__("url", function () {
        return qnx.callExtensionMethod("webview.location", this.id);
    });

    this.__defineSetter__("url", function (newUrl) {
        qnx.callExtensionMethod("webview.loadURL", this.id, newUrl);
    });

    this.__defineGetter__("originalLocation", function () {
        return qnx.callExtensionMethod("webview.originalLocation", this.id);
    });

    this.__defineGetter__("enableCrossSiteXHR", function () {
        return qnx.callExtensionMethod("webview.isEnableCrossSiteXHR", this.id);
    });

    this.__defineSetter__("enableCrossSiteXHR", function (shouldEnable) {
        qnx.callExtensionMethod("webview.setEnableCrossSiteXHR", this.id, shouldEnable);
    });

    this.__defineSetter__("enableDialogRequestedEvents", function (shouldEnable) {
        qnx.callExtensionMethod('webview.setEnableDialogRequestedEvents', this.id, shouldEnable);
    });

    this.__defineGetter__("enableDialogRequestedEvents", function () {
        return qnx.callExtensionMethod('webview.isEnableDialogRequestedEvents', this.id);
    });

    this.__defineGetter__("enableWebInspector", function () {
        return qnx.callExtensionMethod("webview.isEnabledOutOfProcessWebInspector", this.id);
    });

    this.__defineSetter__("enableWebInspector", function (shouldEnable) {
        qnx.callExtensionMethod("webview.setEnabledOutOfProcessWebInspector", this.id, shouldEnable);
    });

    this.__defineGetter__("setFileSystemSandbox", function () {
        return qnx.callExtensionMethod("webview.fileSystemAPISandboxed", this.id);
    });

    this.__defineSetter__("setFileSystemSandbox", function (shouldEnable) {
        qnx.callExtensionMethod("webview.setFileSystemAPISandboxed", this.id, shouldEnable);
    });

    this.__defineGetter__("autoDeferNetworkingAndJavaScript", function () {
        return qnx.callExtensionMethod("webview.isAutoDeferNetworkingAndJavaScript", this.id);
    });

    this.__defineSetter__("autoDeferNetworkingAndJavaScript", function (shouldAutoDeferNetworkingAndJavaScript) {
        qnx.callExtensionMethod("webview.setAutoDeferNetworkingAndJavaScript", this.id, shouldAutoDeferNetworkingAndJavaScript);
    });

    this.__defineGetter__("allowQnxObject", function () {
        return _qnxObjectEnabled;
    });

    this.__defineSetter__("allowQnxObject", function (shouldEnable) {
        _qnxObjectEnabled = shouldEnable;
        qnx.callExtensionMethod("webview.enableQnxJavaScriptObject", this.id, shouldEnable);
    });


    function setListener(eventName, listener) {
        var methodName = "on" + eventName;
        if (listener && typeof listener === 'function') {
            events.on(_id, eventName, listener);
            _listeners[methodName] = listener;
            return true;
        } else {
            //If an invalid callback is set, clear the listener
            events.removeEventListener(_id, eventName, _listeners[methodName]);
            delete _listeners[methodName];
            return false;
        }
    }

    this.__defineGetter__("onNetworkResourceRequested", function () {
        return _listeners["onNetworkResourceRequested"];
    });

    this.__defineSetter__("onNetworkResourceRequested", function (listener) {
        var hasListener = setListener("NetworkResourceRequested", listener);
        qnx.callExtensionMethod("webview.setEnableNetworkResourceRequestedEvents", this.id, hasListener);
    });

    internal.sendEvents.forEach(function (element, index, array) {
        var methodName = "on" + element;
        that.__defineGetter__(methodName, function () {
            return _listeners[methodName];
        });

        that.__defineSetter__(methodName, function (listener) {
            setListener(element, listener);
        });
    });

    _defaultHandlers.forEach(function (defaultHandler) {
        that[defaultHandler] = require('./defaultHandlers/' + defaultHandler).handle;
    });
}




/**#@+
* @param {String} eventType The native event to be listened to.<b> Only the following events can be listened to or the method will fail silently.</b><br/>
* Can be one of
        'ContentRendered',
        'ContextMenuCancelEvent',
        'Created',
        'Destroyed',
        'DocumentLoadCommitted',
        'DocumentLoaded',
        'DocumentLoadFinished',
        'DialogRequested'
        'JavaScriptCallback',
        'JavaScriptResult',
        'LocationChange',
        'NetworkError',
        'PropertyActiveEvent',
        'PropertyBackgroundColorEvent',
        'PropertyCanGoBackEvent',
        'PropertyCanGoForwardEvent',
        'PropertyCertificateInfoEvent',
        'PropertyContentRectangleEvent',
        'PropertyCurrentContextEvent',
        'PropertyEnableWebInspectorEvent',
        'PropertyEncryptionInfoEvent',
        'PropertyFaviconEvent',
        'PropertyHistoryListEvent',
        'PropertyHistoryPositionEvent',
        'PropertyJavaScriptInterruptTimeoutEvent',
        'PropertyLoadProgressEvent',
        'PropertyLocationEvent',
        'PropertyOriginalLocationEvent',
        'PropertyScaleEvent',
        'PropertyScrollPositionEvent',
        'PropertySecureTypeEvent',
        'PropertyStatusEvent',
        'PropertyTitleEvent',
        'PropertyTooltipEvent',
        'PropertyVisibleEvent',
        'PropertyWebInspectorPortEvent',
        'PropertyViewportEvent',
        'PropertyZOrderEvent',
        'QNXWebDestroyedEvent',
**/

/**
 * @description Adds a listener for a given event. Multiple listeners can be registered for the same event.
 * @param {callback} eventListener The function to be invoked when the event occurs
*/
WebView.prototype.addEventListener = function (eventType, eventListener) {
    if (internal.sendEvents.indexOf(eventType) === -1 && eventType !== "NetworkResourceRequested") {
        events.on(this.id, eventType, eventListener); //What to put for scope???
    }
};

/**
 * @description Removes a specific registered listener for a given event
 * @param {Object} eventListener The function to be removed from the list of event listeners
*/
WebView.prototype.removeEventListener = function (eventType, eventListener) {
    if (internal.sendEvents.indexOf(eventType) === -1 && eventType !== "NetworkResourceRequested") {
        events.removeEventListener(this.id, eventType, eventListener);
    }
};

/**
 * @description Dispatches an event of the provided type with the given arguments to all registered listeners.
 * @param {Object[]} args The array of objects to be passed to the event
*/
WebView.prototype.dispatchEvent = function (eventType, args) {
    if (internal.sendEvents.indexOf(eventType) === -1 && eventType !== "NetworkResourceRequested") {
        events.emit(this.id, eventType, args);
    }
};

/**#@-*/

/**
* @description Sets the location of the webview on the screen
* @param {Number} x The x position of the webview
* @param {Number} y The y position of the webview
* @param {Number} width The width of the webview
* @param {Number} height The height of the webview
*/
WebView.prototype.setGeometry = function (x, y, width, height) {
    qnx.callExtensionMethod("webview.setGeometry", this.id, x, y, width, height);
};

/**
* @description Destroys the underlying native webview
* @param {callback} [onComplete] A callback to be invoked when the destruction call is complete
*/
WebView.prototype.destroy = function (onComplete) {
    qnx.callExtensionMethod("webview.destroy", this.id);
    //Clear all event listeners and published functions for this webview
    events.clear(this.id);
    rpc.clear(this.id);

    if (onComplete && typeof onComplete === 'function') {
        onComplete();
    }
};

/**
* @description Executes javascript in the context of the webview
* @param {String} js The javascript expression to be executed
     * @param {boolean} [inIsolatedWorld=false] Run javascript in isolated context
     * @param {callback} [onComplete] A callback to be invoked when the destruction call is complete
*/
WebView.prototype.executeJavaScript = function (js, inIsolatedWorld, onComplete) {
    qnx.callExtensionMethod("webview.executeJavaScript", this.id, js, inIsolatedWorld ? "IsolatedWorld" : "NormalWorld");
    if (onComplete && typeof onComplete === 'function') {
        onComplete();
    }
};

/**
 * @description Sets the background color of the webview
 * @param {String} color The desired background color of the webview in hex
 * @example webview.setBackgroundColor("0x00FFFFFF");
 */
WebView.prototype.setBackgroundColor = function (color) {
    qnx.callExtensionMethod("webview.setBackgroundColor", this.id, color);
};

/**
 * @description Notifies native that stuff is opened
 * @param {Number} streamId The streamId of the stream that has been opened
 * @param {String} responseCode The response to the opening of it
 * @param {String} value The value you wish to notify native of
 */
WebView.prototype.notifyOpen = function (streamId, responseCode, value) {
    qnx.callExtensionMethod("webview.notifyOpen", this.id, streamId, responseCode, value);
};

/**
 * @description Notifies native that the header is received
 * @param {Number} streamId The streamId of the stream that has been opened
 * @param {String} responseCode The response to the opening of it
 * @param {String} value The value you wish to notify native of
 */
WebView.prototype.notifyHeaderReceived = function (streamId, responseCode, value) {
    qnx.callExtensionMethod("webview.notifyHeaderReceived", this.id, streamId, responseCode, value);
};

/**
 * @description Notifies native that the data is received
 * @param {Number} streamId The streamId of the stream that has been opened
 * @param {String} responseCode The response to the opening of it
 * @param {String} value The value you wish to notify native of
 */
WebView.prototype.notifyDataReceived = function (streamId, responseCode, value) {
    qnx.callExtensionMethod("webview.notifyDataReceived", this.id, streamId, responseCode, value);
};

/**
 * @description Notifies native that the webview is done rotating
 */
WebView.prototype.notifyApplicationOrientationDone = function () {
    qnx.callExtensionMethod("webview.notifyApplicationOrientationDone", this.id);
};

/**
 * @description Notifies native that everything is done
 * @param {Number} streamId The streamId of the stream that has been opened
 */
WebView.prototype.notifyDone = function (streamId, responseCode, value) {
    qnx.callExtensionMethod("webview.notifyDone", this.id, streamId);
};

/**
 * @description Notifies native that the context menu has been dismissed
 */
WebView.prototype.notifyContextMenuCancelled = function () {
    qnx.callExtensionMethod("webview.notifyContextMenuCancelled", this.id);
};

/**
 * @description Publishes a name that maps to a specific function.  Allows other WebViews to request execution of the handler.
 * @param {String} name The name of the function to be published
 * @param {Function} handler Function that will be published
 * @param {Object} options Optional configuration object.  Subparameters are "scope" and "once"
*/
WebView.prototype.publishRemoteFunction = function (name, handler, options) {
    rpc.publish(this.id, name, handler, options);
};

/**
 * @description Removes a published function name
 * @param {String} name Name of the function to unpublish
*/
WebView.prototype.unpublishRemoteFunction = function (name) {
    rpc.unpublish(this.id, name);
};

/**
 * @description Performs a remote function call on another WebView
 * @param {Number} webviewId ID of the target WebView
 * @param {String} name Name of the function to be executed
 * @param {Object[]} args Arguments for the desired function
 * @param {boolean} sync Optionally set to run synchronously.  Default is false.
 * @param {Function} callback Optional callback that runs on completion.  Ignored on synchronous calls.
*/
WebView.prototype.remoteExec = function (webviewId, name, args, sync, callback) {
    rpc.remoteExec(webviewId, name, args, sync, callback);
};

/**
 * @description Redirects web events intended for this WebView to another WebView
 * @param {String} eventType Name of the event to redirect
 * @param {Number} targetWebView ID of the WebView that will receive the event
 * @param {String} returnVal Optional return value for the event
*/
WebView.prototype.enableWebEventRedirect = function (eventType, targetWebViewId, returnVal) {
    internal.enableWebEventRedirect(eventType, this.id, targetWebViewId, returnVal);
};

/**
 * @description Stops web event redirection for a particular event
 * @param {String} eventType Name of the event to stop redirecting
*/
WebView.prototype.disableWebEventRedirect = function (eventType) {
    internal.disableWebEventRedirect(eventType, this.id);
};

/**
 * @description Used as the entry point of the rpc channel to run a callback with parameters
 * @param {Number} callbackId ID of the desired callback to run
 * @param {String} args Stringified parameters for the callback
*/

WebView.prototype.runRemoteExecCallback = function (callbackId, args) {
    rpc.runRemoteExecCallback(callbackId, args);
};

/**
 * @description Sets orientation of the WebView.
 * @param {Number} angle Angle of desired orientation
*/

WebView.prototype.setApplicationOrientation = function (angle) {
    qnx.callExtensionMethod("webview.setApplicationOrientation", this.id, angle);
};

/**
 * @description Sets an extra plugin directory for the WebView.
 * @param {String} directory Path to the extra directory [i.e. '/usr/lib/browser/plugins']
*/

WebView.prototype.setExtraPluginDirectory = function (directory) {
    qnx.callExtensionMethod('webview.setExtraPluginDirectory', this.id, directory);
};

/**
 * @description Allows the webview to continue the SSL Handshaking if an SSLHandshakingFailed
 * event was triggered and caused the SSL handshake to be paused.
 * @param {Number} streamId The SSL stream id from the SSLHandshakingFailed event
 * @param {String} SSLAction The SSLAction can be one of: SSLActionTrust, SSLActionReject or SSLActionNone
*/

WebView.prototype.continueSSLHandshaking = function (streamId, SSLAction) {
    qnx.callExtensionMethod("webview.continueSSLHandshaking", this.id, streamId, SSLAction);
};

/**
 * @description Allows the WebView to add a known SSL Certificate to it's stored
 * list of known certificates. This allows WebViews to remember certificate exceptions.
 * @param {String} url The url of the website for which we wish to add a known certificate
 * @param {String} certificateInfo The certificate info passed from the SSLHandshakingFailed event
*/

WebView.prototype.addKnownSSLCertificate = function (url, certificateInfo) {
    qnx.callExtensionMethod("webview.addKnownSSLCertificate", this.id, url, certificateInfo);
};

/**
 * @description Allows the webview to add whitelist access between two origins. This will allow cross origin communication
 * that would not otherwise be possible.
 * @param {String} sourceOrigin The URI of the source where a network request is created. Use local:// for local access.
 * @param {String} destination The URI of the destination of a network request
 * @param {Boolean} [allowSubdomains=False] Whether subdomains of the source/destination origins should be allowed as well.
 */
WebView.prototype.addOriginAccessWhitelistEntry = function (sourceOrigin, destination, allowSubdomains) {
    qnx.callExtensionMethod("webview.addOriginAccessWhitelistEntry", this.id, sourceOrigin, destination, !!allowSubdomains);
};

/**
 * @description Allows the webview to remove previously added whitelist entries.
 * @param {String} sourceOrigin The URI of the source where a network request is created. Use local:// for local access.
 * @param {String} destination The URI of the destination of a network request
 * @param {Boolean} [allowSubdomains=False] Whether subdomains of the source/destination origins should be allowed as well.
 */
WebView.prototype.removeOriginAccessWhitelistEntry = function (sourceOrigin, destination, allowSubdomains) {
    qnx.callExtensionMethod("webview.removeOriginAccessWhitelistEntry", this.id, sourceOrigin, destination, !!allowSubdomains);
};

/**
 * @description Tells native to download the corresponding URL
 * @param {String} url The url to be downloaded
 */
WebView.prototype.downloadURL = function (url) {
    qnx.callExtensionMethod("webview.downloadURL", this.id, url);
};

/**
 * @description Tells native to handle the context menu response based on the given action
 * @param {String} action The id of the context menu action to be handled.
 */
WebView.prototype.handleContextMenuResponse = function (action) {
    qnx.callExtensionMethod("webview.handleContextMenuResponse", this.id, action);
};

/**
 * @description Allows the WebView to add a known Geolocation permissions for a
 * specific site. This would suppress any notifications from WebKit.
 * @param {String} origin Domain of the website that we wish to allow geolocation permission
*/
WebView.prototype.allowGeolocation = function (origin) {
    qnx.callExtensionMethod("webview.setAllowGeolocation", this.id, origin, true);
};

/**
 * @description Sets the current WebView to disallow Geolocation based on the
 * origin parameter passed in.
 * @param {String} origin Origin of the website for which we wish to add a geolocation permission for this
 * is based on the domain used, sub pages are automatically affected.
*/
WebView.prototype.disallowGeolocation = function (origin) {
    qnx.callExtensionMethod("webview.setAllowGeolocation", this.id, origin, false);
};

/**
 * @description Allows the WebView to add a known Geolocation permissions for a
 * specific site. This would suppress any notifications from WebKit.
 * @param {String} origin Origin of the website for which we wish to check the geolocation
 * value. This is based on the domain.
*/
WebView.prototype.isGeolocationAllowed = function (origin) {
    return qnx.callExtensionMethod("webview.isEnableGeolocation", this.id, origin);

};

/**
 * @description Allows the WebView to add notification permissions for a
 * specific site. This would suppress any notifications from WebKit.
 * @param {String} origin of the website for which we wish to add notification permission for
*/

WebView.prototype.allowNotifications = function (origin) {
    qnx.callExtensionMethod("webview.setAllowNotification", this.id, origin, true);
};

/**
 * @description Disallows the WebView to add notification permissions for a
 * specific site. This would suppress any notifications from WebKit.
 * @param {String} origin of the website for which we wish to add notification permission for
*/

WebView.prototype.disallowNotifications = function (origin) {
    qnx.callExtensionMethod("webview.setAllowNotification", this.id, origin, false);
};


module.exports = WebView;

});
/*
 * 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.
 */


/**
 * @exports _self as qnx.webplatform
 * @namespace qnx.webplatform
*/

qnx.webplatform = (function () {
    var WebView = require("WebView"),
        Application = require("Application"),
        chrome = require("chrome"),
        internal = require("chrome/internal"),
        pps = require("pps"),
        _controller,
        _application,
        _originalInternalObj;


    _controller = new WebView({WebViewId : chrome.id});
    _application = new Application();

    //Only two possible cases should be chrome does not exist
    //OR someone is already implementing webEvent and we will hijack
    //but we'll be cautious just in case
    if (!window.chrome) {
        window.chrome = {};
    }
    if (!window.chrome.internal) {
        window.chrome.internal = {};
    }
    
    function bindInternalObject(objName, internalObj) {
        if (!window.chrome.internal[objName]) {
            window.chrome.internal[objName] = internalObj;
        } else {
            _originalInternalObj = {};

            Object.getOwnPropertyNames(internalObj).forEach(function (funcName) {
                _originalInternalObj[funcName] = window.chrome.internal[objName][funcName];
                //Hijack the function and call ours upstream
                window.chrome.internal[objName][funcName] = function () {
                    internalObj[funcName].apply(this, arguments);
                    if (_originalInternalObj[funcName]) {
                        _originalInternalObj[funcName].apply(this, arguments);
                    }
                };
            });
        }
    }

    bindInternalObject('webEvent', internal.webEvent);
    bindInternalObject('invocation', internal.invocation);
    bindInternalObject('application', internal.application);
    bindInternalObject('pps', internal.pps);

    return {
        /**
         * @description This method creates a new webview object, it can accept the options parameter or just the onCreate callback for legacy support purposes.
         * @param {Object} Optional the options object allows the developer to pass in different options to the WebView object, processType, WebViewId, or the onCreate method.
         * @param {Function} onCreate A callback that will be fired when the native side creates the webview. Clients are expected to implement this as the native side will throw errors if the user attempts to access the webview before the event occures.
         * @returns {WebView} A webview object
         * @example
         * qnx.webplatform.getController().enableWebInspector(true);
         *
         * var webview = qnx.webplatform.createWebView(function (value, eventId) {
         *     webview.setGeometry(0, 0, screen.width, screen.height);
         *     webview.visible = true;
         *     webview.active = true;
         *     console.log("woot");
         * });
         */
        createWebView : function (options, onCreate) {
            var args = {};
            if (options && typeof options === 'function') {
                args.onCreate = options;
            } else {
                args = options ? options : {};
                args.onCreate = onCreate;
            }
            return new WebView(args);
        },

        /**
         * @description This method returns the Webview object for the controller
         * @returns {WebView} The controller webview
         */
        getController : function () {
            return _controller;
        },

        /**
         * @description This method returns the Application object
         * @returns {Application} The Application
         */
        getApplication : function () {
            return _application;
        },

        /**
         * @description This method returns the PPS namespace for creating PPS objects
         * @returns {pps}: The PPS namespace
         */
        pps : pps
    };
}());


}())