You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by Apache Wiki <wi...@apache.org> on 2013/02/01 22:35:25 UTC
[Cordova Wiki] Update of "PluginDesign" by FilMaj
Dear Wiki user,
You have subscribed to a wiki page or wiki category on "Cordova Wiki" for change notification.
The "PluginDesign" page has been changed by FilMaj:
http://wiki.apache.org/cordova/PluginDesign?action=diff&rev1=8&rev2=9
Comment:
Added alunny's plugin spec
- = Plugin Design =
+ = Cordova Plugin Specification =
- Great first pass at a [[https://github.com/deedubbu/cordova-blackberry-pluggable|big picture pluggable BlackBerry WebWorks-based implementation]] courtesy of Drew. Awesome start!
+ Last edited August 16, 2012
- == Plugin Name Convention ==
+ == About this document ==
+ This document defines a format for distributing and packaging plugins for use with Apache Cordova, nee PhoneGap. It is based on the work done as part of the PhoneGap Build (https://build.phonegap.com) web service, where many of the tools and techniques have been implemented. Originally this document was authored at http://github.com/alunny/cordova-plugin-spec.
- * cordova-plugin-xxx
- * clearly a plugin for the Cordova framework
- * in the Web community, lowercase and dashes are common
- * cordova-xxx
- * shorter name
- * puts a plugin on par with a framework, which can be confusing
- == Directory Structure ==
-
- Below are examples based on existing prototype implementations.
-
- * Based on [[https://github.com/deedubbu/cordova-blackberry-pluggable|Drew's prototype]], JavaScript and native code is packaged in the same directory. It is a bit tied to the specifics of the WebWorks platform, but the general structure is:
- * All plugins plus the core framework are encapsulated as extensions, which is a WebWorks concept. These extensions package up any necessary JS and native code.
- * Each extension is included with your final application via declaring specific {{{<feature>}}} elements in your application's config.xml file. Each {{{<feature>}}} maps to a specific extension: either the core framework or a plugin.
-
- == Meta Files ==
-
- TBD
-
- == Documentation ==
-
- * handwritten in Markdown
- * rendered at build-time from tooling
- * rendered from Markdown file or embedded comments
- * simple process, think README.md
-
- == JavaScript files ==
-
- * Taking advantage of the plugin interfaces defined in the [[http://git-wip-us.apache.org/repos/asf?p=cordova-js.git;a=summary|cordova-js]] project:
- * Using the {{{exec}}} function that is referencerable by calling {{{cordova.require('cordova/exec')}}} regardless of platform.
- * {{{exec}}} function has the signature {{{function(successCallback, errorCallback, service, action, args}}}, with the arguments:
- * {{{successCallback}}} - function that native can invoke by calling their {{{success}}} method and optionally pass in arguments
- * {{{errorCallback}}} - function that native can invoke by calling their {{{error}}} method and optionally pass in arguments
- * {{{service}}} - the native plugin label that maps to the desired native plugin. Each native platform has a different mapping mechanism - see the below Native Files section for more details
- * {{{action}}} - the native plugin method label that maps to the desired native plugin method. Each native platform has a different mapping mechanism - see below under Native Files section for more details
- * {{{args}}} - an Array of parameters to pass into the native plugin methods
- * Recommended to use {{{cordova.define}}} as module definition wrapper that conforms with cordova.
- * No JavaScript requirements on namespacing plugins (used to be that all plugins were added to a {{{window.plugins}}} object). This should be up to the plugin author.
-
- == Native Files ==
-
- * Taking advantage of the plugin interfaces defined for each platform:
- * iOS: The [[http://git-wip-us.apache.org/repos/asf?p=cordova-ios.git;a=blob;f=CordovaLib/Classes/CDVPlugin.h;h=662d4e9de9a3369b0fd14ceb225a83f9f87b4e69;hb=HEAD|CDVPlugin interface]]. Also available is a [[http://git-wip-us.apache.org/repos/asf?p=cordova-ios.git;a=blob;f=guides/Cordova+Plugin+Upgrade+Guide.md;h=e0e4b3ca8f2e9369da7d6984823e41afcb9b367c;hb=HEAD|Cordova Plugin Upgrade guide]]. iOS has an explicit mapping of JavaScript {{{exec}}} function's {{{service}}} plugin labels to iOS class names in the [[http://git-wip-us.apache.org/repos/asf?p=cordova-ios.git;a=blob;f=Cordova-based+Application/Cordova.plist;h=eaf4824f3b5627637ed8715e9603b76b688d5883;hb=HEAD|Cordova.plist file]]. {{{exec}}}'s {{{service}}} parameter maps directly to methods implemented in the CDVPlugin.
- * Android: The [[http://git-wip-us.apache.org/repos/asf?p=cordova-android.git;a=blob;f=framework/src/org/apache/cordova/api/Plugin.java;h=648e86d6c3eb9a0c62726cc9d238dcb4c19ccd54;hb=HEAD|Plugin]] interface. Android maps JavaScript {{{exec}}} {{{service}}} labels to Android Plugin classes using the [[http://git-wip-us.apache.org/repos/asf?p=cordova-android.git;a=blob;f=framework/res/xml/plugins.xml;h=ce978fb48b9b171283739e057b58226924ccf75b;hb=HEAD|plugins.xml file]]. The Plugin class' {{{execute}}} [[http://git-wip-us.apache.org/repos/asf?p=cordova-android.git;a=blob;f=framework/src/org/apache/cordova/api/Plugin.java;h=648e86d6c3eb9a0c62726cc9d238dcb4c19ccd54;hb=HEAD#l46|method]] picks up on the {{{service}}} label as a parameter.
- * WP7: The [[https://github.com/apache/cordova-wp7/blob/master/framework/Cordova/Commands/BaseCommand.cs|BaseCommand]]. BaseCommands are created by reflecting on assemblies at runtime (thus lazily loaded) and mapping the {{{service}}} parameter directly to the class name. Similarly the {{{action}}} label maps directly to the method name.
- * BlackBerry: Identical to Android's implementation. There is a [[https://github.com/apache/cordova-blackberry-webworks/blob/master/framework/ext/src/org/apache/cordova/api/Plugin.java|Plugin]] class. A [[https://github.com/apache/cordova-blackberry-webworks/blob/master/template/project/www/plugins.xml|plugins.xml]] file maps {{{service}}} labels to class names. The Plugin's {{{execute}}} function should parse the passed-in {{{action}}} label to determine what method to fire on the native plugin.
- * Playbook: TBD
- * Bada: TBD
-
- == Tooling ==
+ == Sample Tooling ==
- TBD
+ * plugman: a node.js based tool to install and remove compliant plugins: https://github.com/imhotep/plugman
+ * Sample Plugins
+ * ChildBrowser: https://github.com/alunny/ChildBrowser
+ * PG-SQLite Plugin: https://github.com/ApplicationCraft/PGSQLitePlugin
+ == Design Goals ==
+
+ The goals of this format are:
+
+ * facilitate programmatic installation and manipulation of plugins
+ * detail the dependencies and components of individual plugins
+ * allow code reuse between different target platforms
+
+ == Structure of a plugin ==
+
+ A plugin is typically a combination of some web/www code, and some native code. However, plugins may have only one of these things - a plugin could be a single JavaScript, or some native code with no corresponding JavaScript.
+
+ Assuming both web code and native code are present, the plugins should be structured like so:
+
+ {{{
+ foo-plugin # top-level directory
+ -- plugin.xml # xml-based manifest, described below
+ -- src # native source-code, to be compiled for a single platform
+ -- android
+ -- Foo.java
+ -- ios
+ -- CDVFoo.h
+ -- CDVFoo.m
+ -- www # assets to be copied into the www directory of the Cordova project
+ -- foo.js
+ -- foo.png
+ }}}
+
+ == Plugin Manifest Format ==
+
+ The plugin.xml file is an XML document in the plugins namespace - http://www.phonegap.com/ns/plugins/1.0. It contains a top-level plugin element defining the plugin, and children that define the structure of the plugin.
+
+ {{{#!wiki caution
+ '''Namespace'''
+
+ The above namespace likely needs to be looked at from an Apache Cordova perspective.
+ }}}
+
+ A sample plugin element:
+
+ {{{
+ <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ id="com.alunny.foo"
+ version="1.0.2">
+ }}}
+
+ === <plugin> element ===
+
+ The plugin element is the top-level element of the plugin manifest. It has the following attributes:
+
+ ==== xmlns (required) ====
+
+ The plugin namespace - http://www.phonegap.com/ns/plugins/1.0. If the document contains XML from other namespaces - for example, tags to be added ot the AndroidManifest.xml file - those namespaces should also be included in the top-level element.
+
+ ==== id (required) ====
+
+ A reverse-domain style identifier for the plugin - for example, com.alunny.foo
+
+ ==== version (required) ====
+
+ A version number for the plugin, that matches the following major-minor-patch style regular expression:
+
+ {{{
+ ^\d+[.]\d+[.]\d+$
+ }}}
+
+ === Child elements ===
+
+ ==== <engines> element ====
+
+ The child elements of the <engines> element specify versions of Apache Cordova-based frameworks that this plugin supports. An example:
+
+ {{{
+ <engines>
+ <engine name="cordova" version="1.7.0" />
+ <engine name="cordova" version="1.8.1" />
+ <engine name="worklight" version="1.0.0" />
+ </engines>
+ }}}
+
+ Similarly to the version attribute for the <plugin> element, the version string specified should matcha a major-minor-patch string conforming to the regular expression:
+
+ {{{
+ ^\d+[.]\d+[.]\d+$
+ }}}
+
+ Engine elements may also have fuzzy matches to avoid repetition, and reduce maintenance when the underlying platform is updated. A minimum of >, >=, < and <= should be supported by tools, such as:
+
+ {{{
+ <engines>
+ <engine name="cordova" version=">=1.7.0" />
+ <engine name="cordova" version="<1.8.1" />
+ </engines>
+ }}}
+
+ Tools may abort plugin installation if the target project does not meet the engine constraints.
+
+ ==== <name> element ====
+
+ A human-readable name for the plugin. The text content of the element contains the name of the plugin. An example:
+
+ {{{
+ <name>Foo</name>
+ }}}
+
+ At this point in time, the tools prototyped for this format do not make use of this element. If this document progresses, localization will also need to be accounted for.
+
+ ==== <asset> element ====
+
+ One or more elements listing the files or directories to be copied into a Cordova app's www directory. A couple of samples:
+
+ {{{
+ <!-- a single file, to be copied in the root directory -->
+ <asset src="www/foo.js" target="foo.js" />
+ <!-- a directory, also to be copied in the root directory -->
+ <asset src="www/foo" target="foo" />
+ }}}
+
+ All assets tags require both a src attribute and a target attribute.
+
+ ===== src (required) =====
+
+ Where the file or directory is located in the plugin package, relative to the plugin.xml document.
+
+ ===== target (required) =====
+
+ Where the file or directory should be located in the Cordova app, relative to the www directory.
+
+ Assets can be targeted to subdirectories - for instance:
+
+ {{{
+ <asset src="www/new-foo.js" target="js/experimental/foo.js" />
+ }}}
+
+ would create the js/experimental directory in the www directory, if not present, and then copy the file new-foo.js as foo.js into that directory.
+
+ If a file exists at the target location, tools based on this specification should stop the installation process and notify the user of the conflict.
+
+ ==== <platform> ====
+
+ Platform tags identify platforms that have associated native code. Tools using this specification can identify supported platforms and install the code into Cordova projects.
+
+ A sample platform tag:
+
+ {{{
+ <platform name="android">
+ <!-- android specific elements -->
+ </platform>
+ <platform name="ios">
+ <!-- ios specific elements -->
+ </platform>
+ }}}
+
+ ===== name (required) =====
+
+ The name attribute identifies a platform as supported - it also associates the element's children with that platform.
+
+ Platform names should be all-lowercase. Platform names, as arbitrarily chosen, are listed:
+
+ {{{
+ android
+ ios
+ blackberry
+ wp7
+ wp8
+ windows8
+ }}}
+
+ Tools may accept alternate names for platforms. Whatever.
+
+ ==== <source-file> ====
+
+ source-file elements identify executable source code that should be installed into a project. A couple of examples:
+
+ {{{
+ <!-- android -->
+ <source-file src="src/android/Foo.java"
+ target-dir="src/com/alunny/foo" />
+ <!-- ios -->
+ <source-file src="CDVFoo.m" />
+ }}}
+
+ As with assets, if a source-file would overwrite an existing file, tools should notify the user and stop, like, right away.
+
+ ===== src (required) =====
+
+ Where the file is located, relative to the plugin.xml file.
+
+ ===== target-dir =====
+
+ A directory where the files should be copied into, relative to the root of the Cordova project.
+
+ In practice, this is most important for Java-based platforms, where a file in the package com.alunny.foo has be located under the directory com/alunny/foo. For platforms where the source directory is not important, plugin authors should omit this attribute.
+
+ ==== <config-file> ====
+
+ Identifies an XML-based configuration file to be modified, where in that document the modification should take place, and what should be modified.
+
+ At this stage in the spec, the config-file element only allows for appending new children into an XML document. The children are XML literals that are the to be inserted in the target document.
+
+ Example:
+
+ {{{
+ <config-file target="AndroidManifest.xml" parent="/manifest/application">
+ <activity android:name="com.foo.Foo"
+ android:label="@string/app_name">
+ <intent-filter>
+ </intent-filter>
+ </activity>
+ </config-file>
+ }}}
+
+ ===== target =====
+
+ The file to be modified, and the path relative to the root of the Cordova project.
+
+ If this file does not exist, tools should self-destruct over a period of ten minutes. Within the first five minutes, the self-destruct procedure MAY be cancelled with the appropriate security clearance. After five minutes have passed, the self-destruct procedure MUST complete.
+
+ Or they could just stop.
+
+ ===== parent =====
+
+ An absolute XPath selector pointing to the parent of the elements to be added to the config file.
+
+ ==== <plugins-plist> ====
+
+ Specifies a key and value to append to the correct AppInfo.plist file in an iOS Cordova project. Example:
+
+ {{{
+ <plugins-plist key="Foo"
+ string="CDVFoo" />
+ }}}
+
+ This may be an implementation detail leaking through, and could be merged with the config-file element at some later point.
+
+ ==== <resource-file> and <header-file> ====
+
+ Like source files, but specifically for platforms that distinguish between source files, headers, and resources (iOS)
+
+ Examples:
+
+ {{{
+ <resource-file src="CDVFoo.bundle" />
+ <resource-file src="CDVFooViewController.xib" />
+ <header-file src="CDVFoo.h" />
+ }}}
+
+ This is probably an implementation detail leaking through, and future versions of this document will likely merge these elements with source-file.
+
+ ==== <framework> ====
+
+ Identifies a framework (usually part of the OS/platform) that the plugin depends on. Example:
+
+ {{{
+ <framework src="libsqlite3.dylib" />
+ }}}
+
+ Tools should identify the framework through the src attribute and attempt to add the framework to the Cordova project, in the correct fashion for a given platform.
+
+ ===== Variables =====
+
+ In certain cases, a plugin may need to make configuration changes dependent on the target application. For example, to register for C2DM on Android, an app with package id com.alunny.message would need a permission like:
+
+ {{{
+ <uses-permission
+ android:name="com.alunny.message.permission.C2D_MESSAGE"/>
+ }}}
+
+ In cases like this (where the content inserted from the plugin.xml file is not known ahead of time), variables can be indicated by a dollar-sign and a series of capital letters, digits and underscores. For the above example, the plugin.xml file would include this tag:
+
+ {{{
+ <uses-permission
+ android:name="$PACKAGE_NAME.permission.C2D_MESSAGE"/>
+ }}}
+
+ Tools using this specification should replace variable references with the correct value, if specified, or the empty string otherwise.
+
+ The value of the variable reference may be detected by the plugin installation tool (in this case, by reading the AndroidManifest.xml file), or specified by the end-user. One approach could be using environment variables:
+
+ {{{
+ $ pluginstall android . ~/my-plugin PACKAGE_NAME=com.foo
+ }}}
+
+ Variable resolution could also be specified programmatically, depending how the plugin installer is called.
+
+ Certain variable names should be reserved - these are listed below.
+
+ '''''$PACKAGE_NAME'''''
+
+ The reverse-domain style unique identifier for the package - corresponding to the CFBundleIdentifier on iOS or the package attribute of the top-level manifest element in an AndroidManifest.xml file.
+
+ == Authors ==
+
+ * Andrew Lunny
+ * Fil Maj
+
+ == Contributors ==
+
+ * Michael Brooks
+ * Mike Reinstein
+