Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Orion/Documentation/Developer Guide/Simple plugin example"

(Few edits)
(Troubleshooting plugin installation)
(64 intermediate revisions by 6 users not shown)
Line 2: Line 2:
  
 
== What is a plugin? ==
 
== What is a plugin? ==
A <i>plugin</i> is an HTML file containing some JavaScript that knows how to connect to the Orion client. Plugins can be hosted on any web server and installed into Orion using their URL.
+
* A <i>plugin</i> is an HTML file containing some JavaScript that knows how to connect to the Orion client. Plugins can be hosted on any web server and installed into Orion using their URL.
 
+
* In order to be useful, a plugin should provide one or more <i>services</i>. When Orion needs a service contributed by a plugin, it loads the plugin inside an IFrame.
In order to be useful, a plugin should provide one or more <i>services</i>. When Orion needs a service contributed by a plugin, it loads the plugin inside an IFrame.
+
* Orion currently supports a set of <dfn>extension points</dfn>: service types that plugins can contribute to, in order to customize the client and add more functionality. These include things like:
 
+
** Adding more commands to the editor toolbar
Orion currently supports a small set of <i>extension points</i>: service types that plugins can contribute to, in order to customize the client and add more functionality. These include things like:
+
** Adding more commands to the navigator view
* Adding more commands to the editor toolbar
+
** Adding content assist for new file types
* Adding more commands to the navigator view
+
** Adding syntax highlighting rules for new file types
* Adding content assist for new file types
+
* Adding syntax highlighting rules for new file types
+
 
For a full list of available services, see the [[Orion/Documentation/Developer_Guide|Developer Guide]].
 
For a full list of available services, see the [[Orion/Documentation/Developer_Guide|Developer Guide]].
  
 
== What you need ==
 
== What you need ==
Every plugin must include the following JavaScript library:
+
Every plugin must minimally include the following JavaScript library: '''<tt>[http://orionhub.org/orion/plugin.js plugin.js]</tt>'''
* <tt>[http://orionhub.org/orion/plugin.js plugin.js]</tt>
+
 
 
You can copy-paste its contents into a &lt;script&gt; tag in your plugin, or load it externally like so:
 
You can copy-paste its contents into a &lt;script&gt; tag in your plugin, or load it externally like so:
<source lang="html4strict">
+
<source lang="html5" enclose="div" >
<script src="plugin.js" />
+
<script src="plugin.js"></script>
 
</source>
 
</source>
 +
The plugin.js file is also an AMD module, so you can alternatively load it through a module loader like [http://requirejs.org/ RequireJS].
 +
<source lang="javascript" enclose="div" >
 +
require(['plugin'], function(PluginProvider) {
 +
    // ...
 +
});
 +
</source>
 +
 +
==== Advanced API usage ====
 +
If you're authoring a plugin that will use [[Orion/Documentation/Developer Guide/Architecture#Object_References|Object References]], you must load an additional script, <code>Deferred.js</code>. Your script section would then look like this:
 +
 +
<source lang="html5" enclose="div">
 +
<script src="Deferred.js"></script>
 +
<script src="plugin.js"></script>
 +
</source>
 +
 +
The plugin we construct in this tutorial does not use Object References, so just <code>plugin.js</code> will suffice.
  
 
== Writing the plugin ==
 
== Writing the plugin ==
Line 26: Line 40:
 
=== Creating the HTML file ===
 
=== Creating the HTML file ===
 
Create a new HTML file called <tt>reversePlugin.html</tt> with the following content:
 
Create a new HTML file called <tt>reversePlugin.html</tt> with the following content:
<source lang="html4strict">
+
 
 +
<source lang="html5" enclose="div">
 
<!DOCTYPE html>
 
<!DOCTYPE html>
 
<html>
 
<html>
 
<head>
 
<head>
    <meta charset="UTF-8" />
+
<meta charset="UTF-8" />
    <title>Reverse Plugin</title>
+
  <title>Reverse Plugin</title>
 
</head>
 
</head>
 
<body></body>
 
<body></body>
 
</html>
 
</html>
 
</source>
 
</source>
What we have now isn't a plugin yet. It's just a bare-bones HTML file. The next step is to include the API we'll need to talk to Orion.
+
Now we have a bare-bones HTML file. The next step is to include the API we need to talk to Orion. Grab the <tt>plugin.js</tt> file (see [[#What you need|What you need]]) and put it in the same folder as <tt>reversePlugin.html</tt>. Then add this inside the &lt;head&gt; tags of the HTML file:
Grab the <tt>plugin.js</tt> file (see [[#What you need|What you need]]) and put it in the same folder as <tt>reversePlugin.html</tt>. Then add this inside the &lt;head&gt; tags of the HTML file:
+
<source lang="html5" enclose="div" start="6">
<source lang="html4strict">
+
<script src="plugin.js"></script>
<script src="plugin.js" />
+
 
</source>
 
</source>
  
 
=== Making it a plugin ===
 
=== Making it a plugin ===
Next, we'll add some code that exposes a service to Orion. Add the following, again inside the &lt;head&gt; tags:
+
Next, we'll add some code that connects our file to Orion. Add the following, again inside the &lt;head&gt; tags:
<source lang="javascript">
+
<source lang="javascript" enclose="div" >
<script>
+
    <script>
    window.onload = function() {
+
        var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
         var provider = new eclipse.PluginProvider();
+
         var provider = new orion.PluginProvider(headers);
 
+
 
         provider.connect();
 
         provider.connect();
     }
+
     </script>
</script>
+
 
</source>
 
</source>
At this point, we've got an honest-to-goodness Orion plugin, albeit one that does nothing. Let's go over the various parts in detail:
+
At this point, we've got an honest-to-goodness Orion plugin, albeit one that does nothing. Let's go over the various parts in detail.
<!-- ** <tt>window.onload</tt> — -->
+
; <tt>var headers = ...</tt>
* <tt>var provider = new eclipse.PluginProvider()</tt> — <span style="background-color: #00ff00;">TODO</span><br>Optionally, an object giving metadata about the plugin can be provided as an argument to the constructor.
+
: An optional object supplying metadata about the plugin's name, version and description. This is used to display information about the plugin on Orion's Settings page.
* <tt>provider.connect();</tt> — <span style="background-color: #00ff00;">TODO</span>
+
; <tt>var provider = new orion.PluginProvider(headers)</tt>
 +
: Creates a new PluginProvider. The PluginProvider may provide one or more services, but right now ours doesn't provide any.
 +
; <tt>provider.connect()</tt>
 +
: This is where the magic happens. When our plugin is activated from Orion, this call opens an asynchronous communication channel. Orion adds information about our plugin, and any service contributions it makes, to the Orion registry.
  
 
=== Registering the service ===
 
=== Registering the service ===
Now we're going to create and register a service with the [[Orion/Documentation/Developer Guide/Plugging into the editor#orion.edit.command|"orion.edit.command"]] service type.
+
Now we're going to expose a service to Orion. We'll create and register a service with the [[Orion/Documentation/Developer Guide/Plugging into the editor#orion.edit.command|orion.edit.command]] service type.
Add the bold lines as shown:
+
Add the additional lines as shown:
 
+
<source lang="javascript" enclose="div" highlight="2-4" >
  window.onload = function() {
+
        var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
    var provider = new eclipse.PluginProvider();
+
        var provider = new orion.PluginProvider(headers);
    <b>var serviceImpl = {   };''
+
        var serviceImpl = { };
    var serviceProperties = {   };
+
        var serviceProperties = { };
    provider.registerServiceProvider("orion.edit.command", serviceImpl, serviceProperties);</b>
+
        provider.registerService("orion.edit.command", serviceImpl, serviceProperties);
    provider.connect();
+
        provider.connect();
  }
+
</source>
 
+
Let's review what was added:
Let's go over what we have now:
+
; <tt>var serviceImpl</tt>
* <tt>var serviceImpl</tt>: This object gives the implementation of our service, the part that will do the actual work. When someone requests our service,<!-- — for example, by getting a <tt>ServiceReference</tt> object and calling getService() &mdash; --> the plugin is loaded into an IFrame, and the service's methods are made available. The <tt>function</tt>-typed properties of the <tt>serviceImpl</tt> object define the service methods.<br />
+
: This object gives the implementation of our service, the part that will do the actual work. When someone requests our service,<!-- — for example, by getting a <tt>ServiceReference</tt> object and calling getService() &mdash; --> our plugin is loaded into an IFrame, and the service's methods are made available. The <tt>function</tt>-typed properties of the <tt>serviceImpl</tt> object define the service methods.
* <tt>var serviceProperties</tt>: Every service provider can supply '''properties''', which is an object that holds metadata about the service provider. <!-- Orion stores these properties when a plugin is installed <span style="background-color: #00ff00;">(?)</span>, and they can later be queried without causing the plugin to be loaded.<br>Properties are often used to filter out service providers that are irrelevant to a particular task. For example, if you're writing a service provider for content assist, you'd specify what file types your provider applies to in its properties. The content assist loader then only loads plugins that provide content assist for the particular file type being edited.  This is important because plugin load can be an expensive operation, so we want to avoid doing it if possible. since these can be queried without loading the plugin itself. --> If you're familiar with Eclipse desktop, you can think of service properties as analogous to the extensions declared in a plugin.xml file.<br />
+
; <tt>var serviceProperties</tt>
* <tt>provider.registerServiceProvider("orion.edit.command", serviceImpl, serviceProperties);</tt>: This call registers our service implementation and properties with the service type [[Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.command|"orion.edit.command"]]. At this point, if we were to install our plugin into Orion, we've got enough to make the Orion editor see our contribution. However, our contribution still does nothing. Let's fix that.<br />
+
: Every service provider can supply '''properties''', which is an object that holds metadata about the service provider. <!-- Orion stores these properties when a plugin is installed <span style="background-color: #00ff00;">(?)</span>, and they can later be queried without causing the plugin to be loaded.<br>Properties are often used to filter out service providers that are irrelevant to a particular task. For example, if you're writing a service provider for content assist, you'd specify what file types your provider applies to in its properties. The content assist loader then only loads plugins that provide content assist for the particular file type being edited.  This is important because plugin load can be an expensive operation, so we want to avoid doing it if possible. since these can be queried without loading the plugin itself. --> If you're familiar with Eclipse desktop, you can think of service properties as analogous to the extensions declared in a plugin.xml file.
 +
; <tt>provider.registerService("orion.edit.command", serviceImpl, serviceProperties);</tt>
 +
: This call registers our service implementation and properties with the service type [[Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.command|"orion.edit.command"]]. At this point, if we tried installing our plugin into Orion, we'd have enough to make the Orion editor see our contribution. However, our contribution still does nothing. Let's fix that.
  
 
=== Implementing the service ===
 
=== Implementing the service ===
 
We'll fill in the <tt>serviceImpl</tt> and <tt>serviceProperties</tt> objects with the actual details of the service.
 
We'll fill in the <tt>serviceImpl</tt> and <tt>serviceProperties</tt> objects with the actual details of the service.
 
Change the <tt>serviceImpl</tt> object to look like this:
 
Change the <tt>serviceImpl</tt> object to look like this:
 
+
<source lang="javascript" enclose="div" >
<source lang="javascript">
+
        var serviceImpl = {
  var serviceImpl = {
+
            run: function(text) {
    run: function(text) {
+
                return text.split("").reverse().join("");
      return text.split("").reverse().join("");
+
            }
    }
+
        };
  };
+
 
</source>
 
</source>
 
+
Note that the functions defined in the service will depend on what service type you're contributing to. In our case, we're contributing to [[Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.command|"orion.edit.command"]], which expects a <tt>run()</tt> function. (See the [[Orion/Documentation/Developer_Guide|Developer Guide]] for a list of extension points and their API.)
Note that the functions defined in the service will depend on what service type you're contributing to. In our case, we're contributing to [[Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.command|"orion.edit.command"]], which expects a <tt>run()</tt> function. (See the [[Orion/Documentation/Developer_Guide|Developer's Guide]] for a list of extension points and their API.)
+
  
 
Change the serviceProperties object to look like this:
 
Change the serviceProperties object to look like this:
<source lang="javascript">
+
<source lang="javascript" enclose="div" >
  var serviceProperties = {  
+
        var serviceProperties = {  
    name: "Reverse Text",
+
            name: "Reverse Text",
    key: ["e", true, true] // Ctrl+Shift+e
+
            key: ["e", true, true] // Ctrl+Shift+e
  };
+
        };
 
</source>
 
</source>
 
 
=== The finished plugin file ===
 
=== The finished plugin file ===
 
Make sure that your copy of <tt>reversePlugin.html</tt> looks like this:
 
Make sure that your copy of <tt>reversePlugin.html</tt> looks like this:
<source lang="javascript">
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 
<!DOCTYPE html>
 
<!DOCTYPE html>
 
<html>
 
<html>
 
<head>
 
<head>
    <meta charset="UTF-8" />
+
  <meta charset="UTF-8" />
    <title>Reverse Plugin</title>
+
  <title>Reverse Plugin</title>
    <script>
+
  <script src="plugin.js"></script>
    window.onload = function() {
+
  <script>
        var provider = new eclipse.PluginProvider();
+
      var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
        var serviceImpl = {
+
      var provider = new orion.PluginProvider(headers);
                run: function(text) {
+
      var serviceImpl = {
                    return text.split("").reverse().join("");
+
              run: function(text) {
                }
+
                  return text.split("").reverse().join("");
            };
+
              }
        var serviceProperties = {  
+
      };
                name: "Reverse Text",
+
      var serviceProperties = {  
                key: ["e", true, true] // Ctrl+Shift+e
+
              name: "Reverse Text",
            };
+
              key: ["e", true, true] // Ctrl+Shift+e
        provider.registerServiceProvider("orion.edit.command", serviceImpl, serviceProperties);
+
      };
        provider.connect();
+
      provider.registerService("orion.edit.command", serviceImpl, serviceProperties);
    }
+
      provider.connect();
 
</script>
 
</script>
 
</head>
 
</head>
Line 130: Line 144:
 
* If you have a personal web server available, you can copy <tt>reversePlugin.html</tt> and <tt>plugin.js</tt> there.
 
* If you have a personal web server available, you can copy <tt>reversePlugin.html</tt> and <tt>plugin.js</tt> there.
 
* If you're using Orionhub, you can put the plugin in a new folder in your Orionhub workspace. Then create a Site Configuration in Orion that launches your folder. See [[Orion/Documentation/User Guide/Getting started#Launching_your_project_as_a_website|Launching your project as a website]].
 
* If you're using Orionhub, you can put the plugin in a new folder in your Orionhub workspace. Then create a Site Configuration in Orion that launches your folder. See [[Orion/Documentation/User Guide/Getting started#Launching_your_project_as_a_website|Launching your project as a website]].
* You can also use a pre-built version at [http://mamacdon.github.com/0.2/reverse/reversePlugin.html|http://mamacdon.github.com/0.2/reverse/reversePlugin.html].
+
* You can also use a pre-built version at [https://orion-plugins.github.io/1.0/plugins/reverse/reversePlugin.html https://orion-plugins.github.io/1.0/plugins/reverse/reversePlugin.html].
  
  
Now that you've got a URL for reversePlugin, install it:
+
Now that you've got a URL for reversePlugin.html, install it into Orion:
* Go to http://yourOrionServer/plugin/install.html#http://yourPluginServer/reversePlugin.html.
+
* Go to http://yourOrionServer/settings/settings.html#,category=plugins,installPlugin=http://yourPluginServer/reversePlugin.html.
 
* You'll be prompted to install the plugin. Click '''Yes'''.
 
* You'll be prompted to install the plugin. Click '''Yes'''.
 +
* You should see a message indicating success. If you get an error, see [[#Troubleshooting plugin installation|Troubleshooting plugin installation]].
  
  
Now let's try it out.
+
Let's try it out.
 
* In Orion, go to the navigator and create a new file called <tt>test.txt</tt>.
 
* In Orion, go to the navigator and create a new file called <tt>test.txt</tt>.
 
* Click on <tt>test.txt</tt> to open the editor.
 
* Click on <tt>test.txt</tt> to open the editor.
* You'll see a new button on the editor toolbar:<br><span style="background-color:#00ff00;">Image</span>
+
* You'll see a menu entry under "Tools" called "Reverse Text".
* Select some text, click the button, and it should be reversed.
+
* Select some text, click the menu entry (Tools -> Reverse Text) and it should be reversed.
 +
 
 +
 
 +
==== Troubleshooting plugin installation ====
 +
So you got a <tt>Plugin handshake timeout</tt> or similar error while trying to install a plugin? Try these troubleshooting tips:
 +
 
 +
; Check that the plugin URL can be loaded.
 +
: Open the plugin's URL in a web browser -- does the page load correctly? If it 404s, it will fail to install into Orion as a plugin.
 +
 
 +
; Check for errors in the plugin.
 +
: Load the plugin's URL in a web browser, then open your browser's developer console. Look for any script errors or missing resources. Is the required library <tt>plugin.js</tt> loaded correctly? Any of these failures can cause the plugin to fail to handshake with Orion.
 +
 
 +
; Check that the plugin is connecting to the framework.
 +
: To call back to Orion at installation time, the plugin must invoke the <tt>PluginProvider.connect()</tt> method. Load the plugin's URL in a web browser, and use a breakpoint (or <tt>console.log()</tt>) to ensure that the <tt>.connect()</tt> method is actually getting called.
 +
 
 +
; Check for mixed content blocking.
 +
: When you attempt to install the plugin into Orion, does a shield icon appear in your address bar? If so, you're hitting the ''mixed content blocking'' feature of your web browser. The most frequent cause is trying to install a plugin from an <tt>http://</tt> URL into an HTTPS Orion server like <tt>orionhub.org</tt>.
 +
[[Image:Mixed-content-chrome.png||top|alt=Mixed content blocking in Chrome]]
 +
[[Image:Mixed-content-firefox.png||top|alt=Mixed content blocking in Firefox]]
 +
 
 +
There are a few ways to resolve this problem:
 +
* [https://support.mozilla.org/en-US/kb/how-does-content-isnt-secure-affect-my-safety Temporarily turn off] the mixed content blocker.
 +
* Host the plugin on an HTTPS server like [https://pages.github.com/ GitHub Pages]. Then install it from its <tt>https://</tt> URL.
 +
* Use an HTTP Orion server instead of HTTPS. Running a local server on <tt>http://localhost</tt> is a good option. Mixed content blocking will not apply in this case.
 +
* Set up an HTTPS server on your local machine, and host your plugin there while you develop.
  
 
== Examples ==
 
== Examples ==
 
Here are some existing plugins we've written. View their source code to see how they work:
 
Here are some existing plugins we've written. View their source code to see how they work:
; http://orionhub.org/plugins/sampleCommandsPlugin.html
+
; [https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.ui/web/plugins/sampleCommandsPlugin.html bundles/org.eclipse.orion.client.ui/web/plugins/sampleCommandsPlugin.html]
 
: Contributes several sample actions to the Orion navigator by using the <tt>orion.navigate.command</tt> service type.
 
: Contributes several sample actions to the Orion navigator by using the <tt>orion.navigate.command</tt> service type.
  
; http://orionhub.org/plugins/htmlSyntaxHighlightPlugin.html
+
; [https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.ui/web/plugins/webEditingPlugin.js bundles/org.eclipse.orion.client.ui/web/plugins/webEditingPlugin.js]
 
: Contributes syntax highlighting support for HTML files by using the <tt>orion.edit.highlighter</tt> service type.
 
: Contributes syntax highlighting support for HTML files by using the <tt>orion.edit.highlighter</tt> service type.
  
; http://mamacdon.github.com/0.2/plugins/beautify/jsbeautify.html
+
; https://orion-plugins.github.io/0.5/plugins/beautify/jsbeautify.html
: Contributes a "Beautify JS" button to the editor toolbar by using the <tt>orion.edit.command</tt> service type. Visit http://mamacdon.github.com for a directory of other available plugins, organized by Orion version.
+
: Contributes a "Beautify JS" button to the editor toolbar by using the <tt>orion.edit.command</tt> service type.
  
; http://mamacdon.github.com/0.2/uglify/uglify-plugin.html
+
Visit [https://orion-plugins.github.io orion-plugins.github.io] for a directory of Orion plugins that you can install and view the source of.
: Contributes an "Uglify JS" button to the editor toolbar byusing the <tt>orion.edit.command</tt> service type.
+
  
 
== See also ==
 
== See also ==
 
* [[Orion/How Tos/Installing A Plugin|Installing a plugin]]
 
* [[Orion/How Tos/Installing A Plugin|Installing a plugin]]

Revision as of 11:18, 24 July 2015

This section explains how to write a plugin for Orion. It is intended for developers who want to extend Orion's functionality.

What is a plugin?

  • A plugin is an HTML file containing some JavaScript that knows how to connect to the Orion client. Plugins can be hosted on any web server and installed into Orion using their URL.
  • In order to be useful, a plugin should provide one or more services. When Orion needs a service contributed by a plugin, it loads the plugin inside an IFrame.
  • Orion currently supports a set of extension points: service types that plugins can contribute to, in order to customize the client and add more functionality. These include things like:
    • Adding more commands to the editor toolbar
    • Adding more commands to the navigator view
    • Adding content assist for new file types
    • Adding syntax highlighting rules for new file types

For a full list of available services, see the Developer Guide.

What you need

Every plugin must minimally include the following JavaScript library: plugin.js

You can copy-paste its contents into a <script> tag in your plugin, or load it externally like so:

<script src="plugin.js"></script>

The plugin.js file is also an AMD module, so you can alternatively load it through a module loader like RequireJS.

require(['plugin'], function(PluginProvider) {
    // ...
});

Advanced API usage

If you're authoring a plugin that will use Object References, you must load an additional script, Deferred.js. Your script section would then look like this:

<script src="Deferred.js"></script>
<script src="plugin.js"></script>

The plugin we construct in this tutorial does not use Object References, so just plugin.js will suffice.

Writing the plugin

Let's make a plugin that adds a button to the toolbar of the Orion editor. When clicked, it will reverse the selected text in the editor. This is not a very useful feature, but it'll be a good introduction to the concepts involved.

Creating the HTML file

Create a new HTML file called reversePlugin.html with the following content:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
   <title>Reverse Plugin</title>
</head>
<body></body>
</html>

Now we have a bare-bones HTML file. The next step is to include the API we need to talk to Orion. Grab the plugin.js file (see What you need) and put it in the same folder as reversePlugin.html. Then add this inside the <head> tags of the HTML file:

 <script src="plugin.js"></script>

Making it a plugin

Next, we'll add some code that connects our file to Orion. Add the following, again inside the <head> tags:

    <script>
        var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
        var provider = new orion.PluginProvider(headers);
        provider.connect();
    </script>

At this point, we've got an honest-to-goodness Orion plugin, albeit one that does nothing. Let's go over the various parts in detail.

var headers = ...
An optional object supplying metadata about the plugin's name, version and description. This is used to display information about the plugin on Orion's Settings page.
var provider = new orion.PluginProvider(headers)
Creates a new PluginProvider. The PluginProvider may provide one or more services, but right now ours doesn't provide any.
provider.connect()
This is where the magic happens. When our plugin is activated from Orion, this call opens an asynchronous communication channel. Orion adds information about our plugin, and any service contributions it makes, to the Orion registry.

Registering the service

Now we're going to expose a service to Orion. We'll create and register a service with the orion.edit.command service type. Add the additional lines as shown:

        var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
        var provider = new orion.PluginProvider(headers);
        var serviceImpl = { };
        var serviceProperties = { };
        provider.registerService("orion.edit.command", serviceImpl, serviceProperties);
        provider.connect();

Let's review what was added:

var serviceImpl
This object gives the implementation of our service, the part that will do the actual work. When someone requests our service, our plugin is loaded into an IFrame, and the service's methods are made available. The function-typed properties of the serviceImpl object define the service methods.
var serviceProperties
Every service provider can supply properties, which is an object that holds metadata about the service provider. If you're familiar with Eclipse desktop, you can think of service properties as analogous to the extensions declared in a plugin.xml file.
provider.registerService("orion.edit.command", serviceImpl, serviceProperties);
This call registers our service implementation and properties with the service type "orion.edit.command". At this point, if we tried installing our plugin into Orion, we'd have enough to make the Orion editor see our contribution. However, our contribution still does nothing. Let's fix that.

Implementing the service

We'll fill in the serviceImpl and serviceProperties objects with the actual details of the service. Change the serviceImpl object to look like this:

        var serviceImpl = {
            run: function(text) {
                return text.split("").reverse().join("");
            }
        };

Note that the functions defined in the service will depend on what service type you're contributing to. In our case, we're contributing to "orion.edit.command", which expects a run() function. (See the Developer Guide for a list of extension points and their API.)

Change the serviceProperties object to look like this:

        var serviceProperties = {
            name: "Reverse Text",
            key: ["e", true, true] // Ctrl+Shift+e
        };

The finished plugin file

Make sure that your copy of reversePlugin.html looks like this:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <meta charset="UTF-8" />
  5.   <title>Reverse Plugin</title>
  6.   <script src="plugin.js"></script>
  7.   <script>
  8.       var headers = { name: "My Plugin", version: "1.0", description: "My first Orion plugin." };
  9.       var provider = new orion.PluginProvider(headers);
  10.       var serviceImpl = {
  11.               run: function(text) {
  12.                   return text.split("").reverse().join("");
  13.               }
  14.       };
  15.       var serviceProperties = {
  16.               name: "Reverse Text",
  17.               key: ["e", true, true] // Ctrl+Shift+e
  18.       };
  19.       provider.registerService("orion.edit.command", serviceImpl, serviceProperties);
  20.       provider.connect();
  21. </script>
  22. </head>
  23. <body></body>
  24. </html>

Testing the plugin

First we need to host our plugin somewhere.


Now that you've got a URL for reversePlugin.html, install it into Orion:


Let's try it out.

  • In Orion, go to the navigator and create a new file called test.txt.
  • Click on test.txt to open the editor.
  • You'll see a menu entry under "Tools" called "Reverse Text".
  • Select some text, click the menu entry (Tools -> Reverse Text) and it should be reversed.


Troubleshooting plugin installation

So you got a Plugin handshake timeout or similar error while trying to install a plugin? Try these troubleshooting tips:

Check that the plugin URL can be loaded.
Open the plugin's URL in a web browser -- does the page load correctly? If it 404s, it will fail to install into Orion as a plugin.
Check for errors in the plugin.
Load the plugin's URL in a web browser, then open your browser's developer console. Look for any script errors or missing resources. Is the required library plugin.js loaded correctly? Any of these failures can cause the plugin to fail to handshake with Orion.
Check that the plugin is connecting to the framework.
To call back to Orion at installation time, the plugin must invoke the PluginProvider.connect() method. Load the plugin's URL in a web browser, and use a breakpoint (or console.log()) to ensure that the .connect() method is actually getting called.
Check for mixed content blocking.
When you attempt to install the plugin into Orion, does a shield icon appear in your address bar? If so, you're hitting the mixed content blocking feature of your web browser. The most frequent cause is trying to install a plugin from an http:// URL into an HTTPS Orion server like orionhub.org.

Mixed content blocking in Chrome Mixed content blocking in Firefox

There are a few ways to resolve this problem:

  • Temporarily turn off the mixed content blocker.
  • Host the plugin on an HTTPS server like GitHub Pages. Then install it from its https:// URL.
  • Use an HTTP Orion server instead of HTTPS. Running a local server on http://localhost is a good option. Mixed content blocking will not apply in this case.
  • Set up an HTTPS server on your local machine, and host your plugin there while you develop.

Examples

Here are some existing plugins we've written. View their source code to see how they work:

bundles/org.eclipse.orion.client.ui/web/plugins/sampleCommandsPlugin.html
Contributes several sample actions to the Orion navigator by using the orion.navigate.command service type.
bundles/org.eclipse.orion.client.ui/web/plugins/webEditingPlugin.js
Contributes syntax highlighting support for HTML files by using the orion.edit.highlighter service type.
https://orion-plugins.github.io/0.5/plugins/beautify/jsbeautify.html
Contributes a "Beautify JS" button to the editor toolbar by using the orion.edit.command service type.

Visit orion-plugins.github.io for a directory of Orion plugins that you can install and view the source of.

See also

Back to the top