Browse files

Merge pull request #87 from timwindsor/master

Sample BB10 Extension for use as a Template
  • Loading branch information...
2 parents cd258ac + 5d5ff3a commit 39c46f9b755588b5e474735c646c398d85b49015 @timwindsor timwindsor committed Aug 10, 2012
Showing with 2,945 additions and 0 deletions.
  1. +3 −0 BB10/
  2. +279 −0 BB10/TEMPLATE/
  3. +3 −0 BB10/TEMPLATE/TestApplication/
  4. +15 −0 BB10/TEMPLATE/TestApplication/config.xml
  5. +34 −0 BB10/TEMPLATE/TestApplication/index.htm
  6. +30 −0 BB10/TEMPLATE/javascript_src/client.js
  7. +87 −0 BB10/TEMPLATE/javascript_src/index.js
  8. +5 −0 BB10/TEMPLATE/javascript_src/manifest.json
  9. +320 −0 BB10/TEMPLATE/native_src/public/plugin.cpp
  10. +70 −0 BB10/TEMPLATE/native_src/public/plugin.h
  11. +222 −0 BB10/TEMPLATE/native_src/public/tokenizer.cpp
  12. +55 −0 BB10/TEMPLATE/native_src/public/tokenizer.h
  13. +172 −0 BB10/TEMPLATE/native_src/src/memory_js.cpp
  14. +50 −0 BB10/TEMPLATE/native_src/src/memory_js.hpp
  15. +30 −0 BB10/TEMPLATE/output/example.memory/client.js
  16. BIN BB10/TEMPLATE/output/example.memory/device/
  17. +87 −0 BB10/TEMPLATE/output/example.memory/index.js
  18. +5 −0 BB10/TEMPLATE/output/example.memory/manifest.json
  19. BIN BB10/TEMPLATE/output/example.memory/simulator/
  20. +512 −0 BB10/TEMPLATE/project/memoryJnext/.cproject
  21. +77 −0 BB10/TEMPLATE/project/memoryJnext/.project
  22. +320 −0 BB10/TEMPLATE/project/memoryJnext/public/plugin.cpp
  23. +70 −0 BB10/TEMPLATE/project/memoryJnext/public/plugin.h
  24. +222 −0 BB10/TEMPLATE/project/memoryJnext/public/tokenizer.cpp
  25. +55 −0 BB10/TEMPLATE/project/memoryJnext/public/tokenizer.h
  26. +172 −0 BB10/TEMPLATE/project/memoryJnext/src/memory_js.cpp
  27. +50 −0 BB10/TEMPLATE/project/memoryJnext/src/memory_js.hpp
@@ -0,0 +1,3 @@
+# Contributing A BlackBerry 10 Extension
+This content will be updated shortly, but for now, take a look at the [TEMPLATE]( sample and use that for your starting point.
@@ -0,0 +1,279 @@
+# WebWorks Extension Example (Memory Extension)
+This document describes how to generate a WebWorks Extension.
+The implementation is split into two parts: [Native](#native) and [JavaScript](#JavaScript)
+The _ext_sample_ folder includes the implementation of an example
+extension that retrieves the current amount of free memory on the device.
+The resources in the _ext_sample_ folder include:
+* TestApplication/ - Resources for a WebWorks application that uses the Memory
+Extension to get the amount of free memory on the device.
+* javascript_src/ - The JavaScript source files of the example Memory Extension.
+* native_src/ - The native source files for the Memory Extension.
+* output/ - An example file structure of a completed extension that can
+be copied into a WebWorks Installation extension folder.
+* project/ - An example file structure of a native extension project that can
+build the native portion of an extension.
+The Memory Extension implementation should be used in conjunction with this
+read me file to understand how to create a WebWorks extension.
+## How to add an WebWorks Extension to your WebWorks Installation
+1. Navigate to the Framework/ext folder of your WebWorks Installation and
+create a folder for your extension.
+2. Copy you JavaScript files to the root folder of your extension folder.
+3. Create a device and a simulator folder in the root of your extension folder.
+4. Build the native portion of your native extension. One shared library for
+the device and another for the simulator.
+5. Copy the shared library for the device into the device folder.
+6. Copy the shared library for the simulator into the simulator folder.
+After completing the above steps you should be able to build WebWorks
+applications that can use your memory extension. If done correctly, the file
+structure of your extension should match the file structure of the output
+folder in the _ext_sample_ folder.
+IMPORTANT: Make sure that your WebWorks applications whitelist the extension
+otherwise the application will not be able to use the extension.
+### <a name="native">Native Part - Overview</a>
+This part of the document will describe:
+1. How to setup a native extension project in eclipse.
+2. The steps needed to implement a JNEXT extension on the native side.
+3. How to build your native extension project.
+### How to create an Extension Project with the [Native SDK](
+1. Open the Momentics IDE. Navigate to the workbench and from the program menu
+select File -> New -> BlackBerry C/C++ Project.
+2. Enter a name for your project in the window that appears and click next.
+3. In the following window, choose C++ for the language, Managed Build for the
+Build Style and an empty shared library project for the project type.
+When you're done click next.
+4. Select the active configuration you want to use for this project then click
+5. If you wish to use a Native SDK that is different from the workspace SDK then
+uncheck the option to use the workspace SDK selection and select a different
+SDK. When you are done, click Finish. You should see your new project appear in
+the Project Explorer window.
+6. In order to build an extension you'll need to import
+[extension resources](#import) into your new project.
+### <a name="import">How to import extension resources</a>
+1. Right click on your project and select the import menu item. In the window
+that appears select the file system as an import source and click next.
+2. The next window will prompt you to provide a path to a folder. Select the
+public and src folders located in the native_src folder of the extension
+template folder. Import both of the folders and their contents. Then click
+finish. Your project should now have a public folder and a source folder which
+contains source and header files. If done correctly, the file structure of your
+project should match the file structure of the project folder in the extension
+template folder.
+After following the instructions below to implement an extension you should
+[build your extension](#buildExtension) for both the device and the simulator.
+### How to implement a JNEXT extension on the native side
+The native and JavaScript portion of a WebWorks extension communicate with each
+other through the use of an extension framework provided by JNEXT. The native
+interface for the JNEXT extension can be viewed in the plugin header file
+located in the public folder of your project. It also contains constants and
+utility functions that can be used in your native code. Your native extension
+must be derived from JSExt which is defined in plugin.h. Therefore your
+extension should include this header file.
+The MemoryExtension sample code included in the _ext&#95;sample_ folder
+implements the native extension interface to JNEXT.
+Each native extension must implement the following callback functions:
+extern char* onGetObjList( void );
+extern JSExt* onCreateObject( const string& strClassName, const string& strObjId );
+The onGetObjList function returns a comma separated list of classes supported by
+this JNEXT extension. It is used by JNEXT to determine the set of classes that
+can be instantiated by this JNEXT extension.
+The onCreateObject function is the other callback that must be implemented by
+the native JNEXT extension. It takes two parameters. The first parameter is the
+name of the class requested to be created from the JavaScript side. Valid names
+are those that are returned in onGetObjList. The second parameter is the unique
+object id for the class. This method returns a pointer to the created extension
+The native extension must also implement the following class:
+class JSExt
+ virtual ~JSExt() {};
+ virtual string InvokeMethod( const string& strCommand ) = 0;
+ virtual bool CanDelete( void ) = 0;
+ std::string m_id;
+The m_id is an attribute that contains the JNEXT id for this object. The id is
+passed to the class as an argument to the constructor. It is needed to trigger
+events on the JavaScript side from native.
+The CanDelete method is used by JNEXT to determine whether your native object
+can be deleted.
+The InvokeMethod function is called as a result from a request from JavaScript
+to invoke a method of this particular object. The only argument to this
+function is a string passed from JavaScript that this method should parse in
+order to determine which method of the native object should be executed.
+If you want the native code to be able to trigger an event on the JavaScript
+side then you'll need to call the SendPluginEvent function which has the
+following signature:
+void SendPluginEvent( const char* szEvent, void* pContext );
+The first parameter is a space delimited string consisting of
+the m_id (inherited attribute from JSExt) followed by the arguments you wish to
+pass to the JavaScript on event function. The second parameter is the
+m_pContext (inherited attribute from JSExt).
+### <a name="buildExtension">How to build your native Extension</a>
+1. Right click your project and select the Clean Project option.
+2. Right click your project again and select Build Configurations -> Build Selected... .
+3. A window will appear that shows all the available build configurations
+for the project. Depending on the profile you wish to use select the Device and
+corresponding Simulator build profiles and click ok.
+4. You should see the shared libraries generated in the folders for each Build
+Configuration that you selected.
+### How to change the name of the build artifact.
+1. Right click on your project and selecting properties.
+2. Expand the C/C++ Build option and select the Settings option.
+3. In the main window select the build configuration you wish to configure and
+select the build artifact tab.
+4. You should see fields for the type, name, extension and prefix of the
+artifact tab which you can modify to change the build artifact that is
+generated. When you have completed your changes then select ok.
+Please note that each modification of the build artifact corresponds to a
+single configuration. If you wish to modify the build artifacts of all the build
+configurations you will need to modify each build configuration.
+## <a name="JavaScript">JavaScript Part - Overview</a>
+Under the javascript_src folder there are following JavaScript files:
+* __client.js__ - Considered to be a client side, exports APIs that are
+accessible from the client's application. _client.js_ file name is mandatory.
+* __index.js__ - Considered to be a server side, exports APIs that are
+accessible from the _client.js_ and able to communicate with _native_ side.
+_index.js_ file name is mandatory.
+* __manifest.json__ - Descriptor defines Whitelisting flag, ID and Dependencies
+for the extension.
+__example.memory__ is the extension ID as it defined in __manifest.js__ and
+serves as a prefix to all methods and fields defined in the __client.js__
+__example.memory__._getMemory_ - Call this method to get free memory bytes
+__example.memory__._monitorMemory_ - Call this method to register and be
+notified of memory events.
+####See sample code below:
+ function memoryUsageCallback(memoryInByte) {
+ alert("Event Callback. Free memory: " + memoryInByte);
+ }
+ var freeMemory = example.memory.getMemory();
+ alert("Free memory: " + freeMemory);
+ example.memory.monitorMemory(memoryUsageCallback);
+## JavaScript Part - In Depth
+The interaction between __client.js__ and __index.js__ is made by using APIs of
+__webworks__ object.
+The client side can make synchronous or asynchronous calls to the server side.
+When making a call to server side, each method in __client.js__ should provide
+the ID, method name and arguments to _execSync_ to get a synchronized call or to
+_execAsync_ when the request is asynchronous. This will result in the invocation
+of a corresponding method name in __index.js__.
+The __webworks__ object has an event API that can be used to communicate between
+the client and server side. The client registers a callback against the event
+API which the server side can trigger. An example of this functionality is the
+monitor memory function which registers a callback on the client side:
+ window.webworks.event.add(_ID, "example.memory.memoryEvent", cb);
+Where the arguments to the function are the feature id, event id and the
+callback. Once the event is registered on the client side it can be triggered
+by the server side whenever the memory usage changes:
+ _event.trigger("example.memory.memoryEvent", arg);
+The server side uses the event id to trigger the client side callback and passes
+the new memory usage as an argument for the callback.
+### JNEXT Interface
+The interaction between __index.js__ and the _native_ side is made by using
+APIs of JNEXT interface. To accomplish this a constructor function
+_MemoryJNext_ is attached to __JNEXT__. The object is expected to have a
+following structure:
+ * _onEvent_ - Events from the _native_ side are passed as a __String__ to
+ this method. _onEvent_ is a mandatory name.
+ * _init_ - It performs several key operations:
+ 1. Requires the module exported by _native_ side -
+ JNEXT.require("memoryJnext"). The name of required module _memoryJnext_ should match the name of a shared library .so file.
+ 2. Creates an object using acquired module and saves the _id_ returned by the
+ call - _self.&#95;id_ = JNEXT.createObject("memoryJnext.Memory").
+ 3. Registers itself to be notified on events so _onEvent_ will be called -
+ JNEXT.registerEvents(_self).
+ * _getId_ - Returns the _id_ previously saved - return _self.&#95;id_.
+ * Methods and fields used by __index.js__ to redirect, when required, calls
+ that initially came from __client.js__ to the _native_ side. This example
+ has two: _getMemoryJNext_ and _monitorMemoryJNext_
+__index.js__ creates a _MemoryJNext_ object and save its instance in variable, then
+redirects calls to methods in __index.js__ to the corresponding _MemoryJNext_ method.
+ //Code in user's app.
+ var freeMemory = example.memory.getMemory();
+ //Code in user app trigger this code in client.js
+ return window.webworks.execSync(_ID, "getMemoryServer", null);
+ //Code in client.js trigger this code in index.js
+ getMemoryServer: function (success, fail, args, env) {
+ ....
+ }
+ //Finally in index.js code that belongs to MemoryJNext object is triggered where
+ //call to native side takes place and returned value is passed back to the user.
+ _self.getMemoryJNext = function () {
+ return JNEXT.invoke(_self._id, "getMemoryNative");
+ };
@@ -0,0 +1,3 @@
+# Where to find the missing file webworks-
+You will find it under Framework/clientFiles/webworks- in your WebWorks SDK installation folder and copy it to this folder.
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<widget xmlns=""
+ xmlns:rim=""
+ version="1.0.0"
+ id="ExampleMemoryExtension">
+ <name>MemoryExtension</name>
+ <content src="index.htm"/>
+ <author>
+ Research In Motion Ltd.
+ </author>
+ <description>The example to show how to develop and use memory extension</description>
+ <feature id="example.memory" required="true" version=""/>
+ <access uri="*"/>
+ <license href="">My License</license>
@@ -0,0 +1,34 @@
+ <head>
+ <title>Example of Memory Extension</title>
+ <script type="text/javascript" src="webworks-"></script>
+ <script type="text/javascript">
+ function getFreeMemory() {
+ var freeMemory = example.memory.getMemory();
+ alert("Free memory: " + freeMemory);
+ }
+ function memoryUsageCallback(memoryInByte) {
+ document.getElementById("memoryUsage").innerHTML = "Free memory: " + memoryInByte;
+ }
+ function monitorMemoryUsage() {
+ var ret = example.memory.monitorMemory(memoryUsageCallback);
+ alert(ret);
+ }
+ </script>
+ </head>
+ <body bgcolor="#FF9900">
+ <div align="center">
+ <button style="width:280px; height: 240px; font-size: 200%; background-color: lightgreen" onclick="getFreeMemory()">
+ Get current free memory
+ </button>
+ <button style="width:280px; height: 240px; font-size: 200%; background-color: lightgreen" onclick="monitorMemoryUsage()">
+ Start monitoring memory
+ </button>
+ <br />
+ </div>
+ <div id="memoryUsage" style="font-size: 200%; background-color: lightblue">
+ </div>
+ </body>
@@ -0,0 +1,30 @@
+* 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
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* See the License for the specific language governing permissions and
+* limitations under the License.
+var _self = {},
+ _ID = require("./manifest.json").namespace;
+_self.getMemory = function () {
+ return window.webworks.execSync(_ID, "getMemoryServer", null);
+_self.monitorMemory = function (cb) {
+ window.webworks.event.add(_ID, "example.memory.memoryEvent", cb);
+ return window.webworks.execSync(_ID, "monitorMemoryServer", null);
+module.exports = _self;
Oops, something went wrong.

0 comments on commit 39c46f9

Please sign in to comment.