Table of contents
Created
26 November 2013
Requirements
Prerequisite knowledge
This article assumes basic familiarity with Creative Suite and Creative Cloud product extensibility.
User level
All
This article will walk you through the entire process of creating an Adobe CC HTML extension from scratch. The resulting extension will allow you to augment the functionality of an Adobe application using HTML, JavaScript, ExtendScript, and CSS.
Here's what you'll need to follow along:
- Your favorite text editor
- An Adobe CC application that supports HTML extensions1
You can also use Extension Builder 3, an Eclipse-based IDE, to help automate some of these steps, however it's not required.
To start, we're going to create two files for our extension, index.html and manifest.xml. The relative location of these files is important and should be arranged:
HelloWorld/
CSXS/
manifest.xml
index.html
HTML
Extensions are hosted in an embedded version of Chromium; that means that nearly everything you can do in Google Chrome, you can also do in an extension. In index.html, let's create a simple UI:
<!doctype html>
<html>
<body>
<button id="btn">Click me</button>
</body>
</html>
Manifest
For our manifest.xml file, we need to provide some metadata for our extension:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ExtensionManifest ExtensionBundleId="com.example.helloworld" ExtensionBundleName="Hello world" ExtensionBundleVersion="1.0" Version="4.0">
<ExtensionList>
<Extension Id="com.example.helloworld.extension" Version="1.0"/>
</ExtensionList>
<ExecutionEnvironment>
<HostList>
<Host Name="PHXS" Version="[14.0,14.9]"/>
</HostList>
<LocaleList>
<Locale Code="All"/>
</LocaleList>
<RequiredRuntimeList>
<RequiredRuntime Name="CSXS" Version="4.0"/>
</RequiredRuntimeList>
</ExecutionEnvironment>
<DispatchInfoList>
<Extension Id="com.example.helloworld.extension">
<DispatchInfo>
<Resources>
<MainPath>./index.html</MainPath>
</Resources>
<UI>
<Type>Panel</Type>
<Menu>Hello world</Menu>
<Geometry>
<Size>
<Height>400</Height>
<Width>400</Width>
</Size>
</Geometry>
</UI>
</DispatchInfo>
</Extension>
</DispatchInfoList>
</ExtensionManifest>
At first glance, the manifest can be a bit overwhelming, so let's go through each section to understand what it's doing.
<ExtensionManifest>
<ExtensionManifest ExtensionBundleId="com.example.helloworld" ExtensionBundleName="Hello world" ExtensionBundleVersion="1.0" Version="4.0">
At the root of the manifest, we provide the id, human readable name, and version of the extension bundle. A bundle is just a collection of extensions; in this bundle, we'll only have one extension to keep things simple. The attribute Version="4.0" should be hardcoded; it defines the manifest version, everything else is up to you to define.
<ExtensionList>
<ExtensionList>
<Extension Id="com.example.helloworld.extension" Version="1.0"/>
</ExtensionList>
Here we specify the list of extensions along with their ids and versions. Again, for this example, we only have one extension.
<HostList>
<HostList>
<Host Name="PHXS" Version="[14.0,14.9]"/>
</HostList>
In the <HostList> section, we define a list of applications our extension will work with. Each application is identified by a 4 character code along with a version range. In this case we're targeting Photoshop CC.
<LocaleList>
<LocaleList>
<Locale Code="All"/>
</LocaleList>
The <LocaleList> section defines the locales your extension will work in. Here we've set up the extension to work for all locales.
<RequiredRuntimeList>
<RequiredRuntimeList>
<RequiredRuntime Name="CSXS" Version="4.0"/>
</RequiredRuntimeList>
The <RequiredRuntimeList> section will be hardcoded for all extensions you create. All it says is that we require version 4.0 of the CSXS runtime (now called CEP).
<Extension>
<Extension Id="com.example.helloworld.extension">
The <Extension> section begins the definition of our extension. The id should match the one defined in the <ExtensionList> section.
<Resources>
<Resources>
<MainPath>./index.html</MainPath>
</Resources>
In the <Resources> section, we point to our index.html file we created earlier, telling the application that this is the HTML we want loaded when the extension is opened.
<UI>
<UI>
<Type>Panel</Type>
<Menu>Hello world</Menu>
<Geometry>
<Size>
<Height>400</Height>
<Width>400</Width>
</Size>
</Geometry>
</UI>
Finally, we have the <UI> section. Here we define the window type of the extension, the menu name (which will show up under Window > Extensions), and the initial dimensions.
Now that we have our code ready to go, the next step is to prepare our environment for development and copy the extension into place. Then we can run the extension.
PlayerDebugMode
Applications will normally not load an extension unless it is cryptographically signed. However, during development we want to be able to quickly test an extension without having to sign it. To turn on debug mode:
- On Mac, open the file ~/Library/Preferences/com.adobe.CSXS.4.plist and add a row with key PlayerDebugMode, of type String, and value 1.
- On Windows, open the registry key HKEY_CURRENT_USER/Software/Adobe/CSXS.4 and add a key named PlayerDebugMode, of type String, and value 1.
You should only need to do this once.
Copying the extension into place
Now that the system is ready to load our unsigned extension, the last thing we have to do is copy our extension into the shared extensions folder on disk:
- On Mac, copy the extension into ~/Library/Application Support/Adobe/CEPServiceManager4/extensions
- On Windows, copy the extension into %APPDATA%\Adobe\CEPServiceManager4\extensions
When you're done you should have a folder structure like this:
extensions/
HelloWorld/
CSXS/
manifest.xml
index.html
Opening the extension
Now we can open the extension in Photoshop CC. Launch the application and choose the menuWindow > Extensions > Hello World. You should see something like this:

Our extension is up and running, now let's debug it.
There are two ways to debug an HTML5 extension.
Method 1 (Deprecated): Debugging can be enabled by calling a special JavaScript function that only works for extensions:
window.__adobe_cep__.showDevTools();
Add this line to a file named main.js and reference the new file from index.html:
<!doctype html>
<html>
<body>
<button id="btn">Click me</button>
</body>
<script src="js/main.js"></script>
</html>
Create a file called .debug in the root folder of your extension.
Note: The above step is necessary with more recent versions of Creative Cloud products. At the time of writing it is only required with Premiere Pro 7.1 and Illustrator 17.0.2. For other products it is not required.
Your current folder structure should look like this:
extensions/
HelloWorld/
CSXS/
manifest.xml
js/
main.js
index.html
.debug
When you open the extension again, you should see the Chromium debugger pop up (note that the debugger UI may differ slightly between versions of Adobe applications):

This window works just like you'd expect if you've debugged in Google Chrome before - you can inspect elements, console output, network performance, etc.
Method 2: Remote Debugging.
Note: Not all Creative Cloud applications support this method at the time of writing.
CEP/CSXS 4.2 supports remote debugging for HTML/JavaScript extensions using the Chrome debugger.
To use this method, you must specify debug ports in a mapping file in your extension's root folder. You can then open the debug port for the host application from a Google Chrome browser and use the Chrome debugging tools. For example, if you have specified the debug port 8088 for Photoshop, and you open your extension in Photoshop, open the Chrome browser and go to http://localhost:8088. Mozilla Firefox and Safari should also work. The browser will display information about your extension and a clickable link to debug the extension. Once you click on that you will see a similar view as when using Method 1.
To specify the debug ports, create a special file named .debug and place it in your extension's root folder; for example, MyExtension\.debug.
Edit this file to include valid remote debug ports for all applications you wish to debug, in the Extension Manifest XML format for <Host> specifications. Valid port values are in the range 1024 to 65534.
With our HelloWorld extension, the file would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<ExtensionList>
<Extension Id="com.example.helloworld.extension">
<HostList>
<Host Name="PHXS" Port="8088"/>
</HostList>
</Extension>
</ExtensionList>
In most cases, your extension won't just be isolated HTML, you'll probably want to interact with the application your extension is running in. To make such calls, we use a library called CSInterface.js (this API is documented in Extension Builder 3).
This library provides a number of useful functions, everything from retrieving the id of the current host application, to programmatically closing your extension. For this demo, we're going to use it to make calls against the host application's scripting DOM.
First, we need to add the library to index.html and copy it into the js folder:
<!doctype html>
<html>
<body>
<button id="btn">Click me</button>
</body>
<script src="js/CSInterface-4.0.0.js"></script>
<script src="js/main.js"></script>
</html>
Next, we're going to add some ExtendScript which will create a new document using Photoshop's scripting DOM. Create a new file called ps.jsx with the code:
function addDocument() {
app.documents.add();
}
Add this new file to a folder called host inside of the extension, so our folder structure now has:
HelloWorld/
CSXS/
manifest.xml
js/
CSInterface-4.0.0.js
main.js
host/
ps.jsx
index.html
At the moment, our script won't be loaded by the extension. In order to wire it up, we have to add a reference to it in our manifest.xml:
<Resources>
<MainPath>./index.html</MainPath>
<ScriptPath>./host/ps.jsx</ScriptPath>
</Resources>
And with that, our ExtendScript function will be loaded when the extension is loaded. The last step is to modify main.js to call this function using CSInterface when the extension's button is clicked:
// Get a reference to a CSInterface object
var csInterface = new CSInterface();
var button = window.document.getElementById("btn");
button.onclick = function() {
// Call function defined in host/ps.jsx
csInterface.evalScript("addDocument()");
};
Finally, when we reload the extension and click on the button, Photoshop should create a new document.
Note: You may also want to check out CEPEngine_extensions which provides APIs to manipulate local files and external processes.
Once our extension has been developed, we'll eventually want to sign and package it for deployment. For that, we're going to use a tool called ZXPSignCmd which is available at the bottom of the Extension Builder 3 download page.
Certificates
Before we can sign and package our extension, we need a certificate. In the real world, we'd buy a certificate from a trusted certificate authority like VeriSign, but for simplicity let's create a self-signed certificate. We can use ZXPSignCmd to self-sign a certificate using the syntax:
ZXPSignCmd -selfSignedCert <countryCode> <stateOrProvince> <organization> <commonName> <password> <outputPath.p12>
For example, the following command will generate the certificate myCertificate.p12:
./ZXPSignCmd -selfSignedCert US Washington myOrganization "John Smith" myPassword myCertificate.p12
Signing and packaging
Now that we have a certificate, we can now sign and package the extension using ZXPSignCmd:
ZXPSignCmd -sign <inputDirectory> <outputZxp> <p12> <p12Password>
For example, using our existing extension and certificate:
./ZXPSignCmd -sign HelloWorld/ HelloWorld.zxp myCertificate.p12 myPassword
Congrats! Now we can distribute the signed HelloWorld.zxp to our users.
At this point, we've touched on all the major components of building an HTML extension. We have:
- Created a simple UI using HTML
- Defined metadata in the manifest
- Setup our environment for running the extension
- Debugged a running extension
- Interacted with the host application using CSInterface and ExtendScript
- Packaged and prepared the extension for deployment
However, even with all that, there's still plenty more to learn. Below is a list of additional resources that will help take you beyond the basics.
Resources
- Using the Adobe Extension SDK - Adobe Extension SDK user guide
- Chromium Embedded Framework - Embedded version of Chromium used to run extensions.
- CEPEngine_extensions - JavaScript library for interacting with files and external processes.
- Exchange - Marketplace for selling your extensions.
- Extension Builder 3 - An IDE for creating HTML extensions for Adobe applications.
- ZXPSignCmd - Command line tool for signing and packaging extensions (bottom of page).