How to write a Hello World Safari Extension in Windows

        We’re going to build a simple Safari extension that will insert a bolded, italicized, Hello World text into the web-page of the current tab after it is loaded.

We’re going to use Safari 5.0 or later in order to have access to Extension Builder, that is, the means by which we’ll build our extension. Extensions were introduced in Safari 5.0, and were disabled by default, so in Safari 5.0 you must enable extensions in the Develop menu before you can show Extension Builder. Extensions are enabled by default in Safari 5.0.1 and later.

[Before we start coding]:
The Safari Extensions Development Guide states that before you can build and install an extension, you need to install a developer certificate. You obtain a certificate by first signing up for the Safari Developer Program at http://developer.apple.com/programs/safari/. You must first create an account and register all your personal information (phone, address, country code, etc – there’s no need of course to enter genuine information if you care for you privacy on the Internet – bogus data will suffice) .

You’ll obtain an Individual ID that will be usable for a period of 12 months. You then have to access http://developer.apple.com/membercenter/index.action and install your certificate by double-clicking the Developer Certificate Utility icon in order to Request and manage your Apple-issued Certificates for Mac and Safari. This launches the Certificate Import Wizard on a Windows machine. You then have to click Create Certificates, then Add Certificate and follow the instructions. Pretty arduous operation compared to what you have to do to get things working in Chrome or Firefox but hey, what are you going to do if you need the thing badly ?! (NOTE: Windows XP Professional and Windows Server 2003 will have to download the following Administration Tools Pack in order to be able to follow the above steps)

After all this you’ll be prompted to download your certificate (safari_identity.cer). You’ll have to double-click the downloaded *.cer file to install it.

[Activating Extension Builder]:
In order to use Extension Builder we’re going to first activate it; we do this by enabling the Safari developer tools when we click “Show Develop menu in menu bar” checkbox in the Advanced pane of Safari Preferences, as shown below. You can access Safari Preferences by clicking the top-right gear button that says “Display a menu of general Safari settings“.

How to activate Develop menu in Safari

How to activate Develop menu in Safari

We then go to the Develop menu and click Show Extension Builder; In the displayed dialog we hit the + button on the left-bottom and click New Extension, chose the path and the folder name and then insert the required fields of your extension:

Extension Info, Details, Versions, Website Access and Global Page Settings

Extension Info, Details, Versions, Website Access, Global Page, and Global Storage Settings

The required fields for the above are :

  • 1. Display Name: the visible name of your extension
  • 2. Bundle Identifier: this is a string in reverse DNS format : your type of website (com, gov, edu, org, and so on), your company name, and the extension name, separated by dots -> ex: com.lexdesign.hello.
  • 3. Display Version: the displayed version number for your extension.
  • 4. Bundle Version, that is, the internal version number used by the OS. One or more digits separated by periods (ex: 1 or 4.1.2). This is the version number Safari uses when checking for updates.
Chrome, Extension Scripts, and Settings

Chrome, Extension Scripts, and Settings

The optional fields above can contain the following :

  • The Extension Chrome section can include am Extension Bar to be included below the bookmarks bar and above the tab bar, which is uniquely reserved for your extension, Context Menu Items, and Toolbar Items, that is, buttons added to the main Safari toolbar (not your specific extension bar).
  • The Injected Extension Content section can include Start Scripts, that is, scripts executed before the webpage is loaded, End Scripts which execute when the body tag’s onload event occurs, and Style Sheets: CSS coding used to style the HTML.

Of course there are a lot of other fields. If you want to get the grips with all of them you can check Apple’s Safari Extensions Development Guide -> Using Extension Builder.

Now that we’ve bootstrapped the basic Safari Extension Starting Kit we will start to code the extension that will insert a bolded, italicized, Hello World text into the web-page of the current tab after it is loaded. This application can have various interesting uses: it could be used to insert specialized controls into specific websites that lack certain idiosyncratic features that the user may demand. Let’s begin!

[Injecting the text]:
inject.js is going to be added as an End Script in the Injected Extension Content section of Extension Builder. Being an end script means that the *.js file will be executed after the body tag’s onload event occurs. We’ll also use jQuery for easy manipulation of the DOM. We’ll insert jQuery as an End Script also.

You can get the latest, Minified (compressed) jQuery from http://docs.jquery.com/Downloading_jQuery.

Here is the inject.js file that will insert our Hello World text :

// <inject.js> insert a Hellow World text into the body of the document

function PageShowHandler(event)
{
	injectText();
}

function injectText()
{
    // get the document body
	var pageBody = jQuery('body', document);
	console.log('entered injectText');
	pageBody.prepend('<h1>Hello World</h1>');
}

// wait 100 ms in order for jquery-1.5.1.min.js to be injected also
// if you don't want to wait just change the order of loading of jquery-1.5.1.min.js
//   and inject.js in Extension Builder-> Injected Extension Content -> End Scripts
setTimeout(PageShowHandler, 100);

Please notice that we use the jQuery .prepend( content, [ content ] ) function that inserts content, specified by the parameter, to the beginning of each element in the set of matched elements.

Also, instead of directly executing the PageShowHandler function to insert our text into the body of the document, we user a timer and waited 100ms in order for jQuery to load. So, if you want to instantly use PageShowHandler, without a time, you should change the order of injection of the two javascript files in Extension Builder -> Injected Extension Content -> End Scripts as below:

The order of injection matters; specify the jQuery file first

The order of injection matters; specify the jQuery file first

More >