One of the exciting new features scheduled to be included in Ubuntu 12.10 (Quantal Quetzal) is the introduction of Web Apps. These consist of a UserScript that bridges the gap between the JavaScript code on the page and the user’s desktop. For example, a script written for Gmail might display a desktop notification when a new message arrives in the user’s inbox. Or perhaps a script written for MySpace would make use of the desktop media player interface to display Title / Artist / Track information for currently playing music.
The wealth of functionality that these new APIs provide open up a wide range of possibilities. The current list of Web Apps with scripts can be viewed here. In fact, I encourage you to click on one of the scripts to get an idea of how it works.
Before I begin explaining the process of writing a script for the API, I should point out that documentation and a simple tutorial already exist. However, the tutorial doesn’t explain some of the details for setting up the script and what you should do with it after you have finished writing it.
Overview
I have always found that the best way to describe a process to someone is by walking them through it. Therefore, I will explain in details the steps I have taken to write a script for Ask Ubuntu. I encourage you to check out the site if you haven’t already to get an idea of how we can best integrate some of the site’s features into the user’s desktop.
First Things First
The very first thing you need to do is to add the webapps PPA to your system and install the unity-webapps-preview package:
sudo add-apt-repository ppa:webapps/preview
sudo apt-get update
sudo apt-get install unity-webapps-preview
After running these commands in a terminal, you will need to log out and in again. Now open Chromium and visit Launchpad. You should see a small bar along the top of the page asking if you want to integrate Launchpad with your desktop.
If you click “Yes”, you will end up with an extra icon in the Launcher among other things:
Try visiting a page on Launchpad with a list of bugs for a project. Open the HUD and start typing part of the title for one of the bugs. Notice that the bugs show up in the list and you can click on them to view more details.
Checking Out the Source
To develop a script for your favorite website, you must first check out a copy of the webapps-applications branch. If you have Bazaar installed, you can simply run the following commands:
mkdir webapps-applications
cd webapps-applications
bzr init
bzr pull lp:webapps-applications
If you do not have Bazaar installed, you will need to run the following command followed by the ones above:
sudo apt-get install bzr
You should now have the latest code from the webapps-applications branch.
Creating the Icons
The next step is to create an icon for the Launcher. In our case, the icon exists in SVG format here. We need to create four images from the SVG file in the following dimensions: 128x128, 64x64, 52x52, and 48x48. The Gimp is an excellent tool for this task. Now open the directory you created in the previous step (the webapps-applications branch) and open the icon-themes/unity-webapps-applications/apps
directory. You will see four directories with names that correspond with the four dimensions listed above. Copy each image to the appropriate directory, ensuring they have the same filename (‘askubuntu.png’ for example).
Now open a terminal and browse to the ‘icon-themes’ directory. Run the following command:
sh build-icon-list.sh
Beginning the Script
We are now ready to begin writing the actual script itself. Open up a text editor and enter the following:
Anyone familiar with JavaScript programming will recognize what we just typed as a set of comments. Anyone familiar with writing UserScripts will recognize that this is a special comment block. It provides some basic details about the script. Of particular importance is the @include
line. This should be a wildcard URL for which this script will be run. In our case, we want it run on every page on the Ask Ubuntu website. Later on, we’ll examine ways we can limit the script’s actions to particular pages.
Now you need to save the script. Browse to the ‘src’ directory of the branch and name the file ‘AskUbuntu.user.js.in’. The extension is important.
Building the Script
In order for your script to be included with the others when the project is built, you will need to add it to the Makefile. Open the file ‘src/Makefile.am’ and locate the ‘EXTRA_DIST’ list. Scroll to the bottom of the list, append a backslash to the last item on the list, and then insert a new line containing the name of the file from the previous step (being sure to maintain the same level of indentation).
If what I just described was confusing and hard to follow, this snippet should clear things up:
...
Tumblr.user.js.in\
AskUbuntu.user.js.in
Now do the same thing for the ‘user_scripts’ list only omit the ‘.in’ at the end of the filename:
...
Tumblr.user.js\
AskUbuntu.user.js
Now we can finally build everything. Open a terminal to the directory containing the branch and run the following three commands:
./autogen.sh
make
sudo make install prefix=/usr
If you get any errors from running the first command, you are probably missing some development packages (which you can easily install with apt-get). The three commands above will be used every time we make changes to our script and want to test it out.
Making the Script Functional
As it stands now the script doesn’t do anything. Add the following lines to the end of the script:
Now try building the script and running it. As soon as you visit the Ask Ubuntu home page, you should receive the usual prompt. If you select “Yes”, you should see a new icon on your launcher for Ask Ubuntu. It still doesn’t do anything much - but we’re making progress.
Actually Making the Script Functional
Let’s add some entries to the HUD. We want to add these entries when the script is initialized - so we will write a function that creates the entries and we will pass the function as the ‘onInit’ parameter to the Unity.Init() call. Here is what our initialization function looks like:
Now modify the Unity.init() call so that the third line becomes:
Try rebuilding the script and running it again. Open the HUD and begin typing “ask”. Our new addition should show up in the list.
Limiting the Script to Certain Pages
Sometimes we only want the script to execute on certain pages. Unfortunately the logic for determining whether the script should run on a certain page usually exceeds what can reasonably be expressed in a wildcard URL. Therefore we must perform the check ourselves. Consider the following function:
This function will check to see if the current page URL begins with “/questions” and can be invoked as follows:
The Launcher icon will only be displayed if the page URL begins with “/questions”. Of course you aren’t limited to using regular expressions for checking the current page. A number of scripts use XPath to look for items in the page’s DOM - a much more flexible approach.
The Final Product
Here is what our script looks like in its entirety:
Now What?
Once you have finished writing your script, you need to write tests for it. Unfortunately I don’t have the time to explain how this works. However, the branch you checked out contains a file ‘doc/walkthrough.txt’ which briefly explains how this is done.
After writing tests, you can commit the changes to the branch you checked out:
bzr commit -m "Created a script for Ask Ubuntu, added icons, and wrote tests for the script."
Assuming you have a Launchpad account (and pretending your LP username is ‘walter’) you can push the code to a separate branch:
bzr push lp:~walter/webapps-applications/askubuntu
You can now propose the branch for merging.