Note: Please see my update on Crossrider status (12 Jan 2016).
As developers (or humans) we need to balance our skills. Sharp focus is valuable, yet tunnel-visioning oneself is not a good idea — there's so much to learn!
While honing my HTML/CSS/JS kung-fu, I was unexpectedly tasked with something new. We needed to create a browser extension to go with Roadmap, a product our company works on.
A completely new area — or so I thought. Some searching showed a simpler path. I could create extensions with my existing experience. Even more — those extensions could share a (more or less) common code base across all mainstream browsers.
I do not intend to do a full comparison of possible frameworks. When we made our choice a year ago one company stood out — Crossrider. After having developed (as I mentioned before), tested, deployed and updated an extension that runs on Chrome, Firefox and Safari, I have to say that Crossrider delivers on the promise of, quoting their front page, “Cross Browser Extensions in Minutes”.
Sold. Here are some notes and observations from this experience.
Our extension allows accessing Roadmap's data and functions (e.g. task start dates, multiple assignments, estimations, time tracking) when viewing to-do items on integrated 3rd-party sites — Basecamp (New and Classic) to start with, with more to come.
You can see (or use, if you register) the result here: Roadmap Extension in Chrome Web Store. Note that the visual style wasn't developed by me, except for a few personal minor touches it was provided by the skillful Roadmap team. My work was to implement the extension: lock, stock and barrel. I mean — markup, style and logic.
This is where it was a discovery process for me: you can't simply bundle all your logic in the same source code, browsers are more nuanced than that. Crossrider introduces three “scopes”, which manage different functional areas of your extension.
allows setting global values used across tabs.
Basically, this part of code handles everything that happens on the page. Any page you visit — browser loads it first, then Crossrider injects and runs your code. You can check if this is the page you need (by URL or any other on-page criteria) and do what you need with it.
“Background” scope performs tasks that are outside of the page context, and are instead “closer” to the browser. For example — manipulating browser tabs, monitoring network requests (a very neat and powerful feature!), configuring display of browser button.
“Popup” scope — speaking of browser buttons, pressing on one opens a special HTML page, which is defined in this “popup” scope. This feature is quite limited, yet still needed to provide a visible way to configure your extension.
While these scopes are separated by their nature, Crossrider offers a handy messaging API, which allows sending data-loaded messages between scopes. For example, if background scope of Roadmap extension detects an “update” network request from Basecamp New, then it tells the page scope to check for changes on the page — since it is possible that new todos were added.
All the API is neatly documented, and the actual development happens in Crossrider's online IDE, which is able to connect to already installed extension in the same browser and update it as needed (except for Safari and Internet Explorer — below I'll share my thoughts on browsers). It is possible to add resource files (you may need it to include CSS, HTML or images, and to modularize your JS code), and in general the IDE is on the simple side, but it does its job. There's even integration with JSHint, which warns about most obvious errors before pushing code update to the extension.
It is also possible to configure a “Debug Mode”,
which allows editing files using your editor of choice,
yet I didn't bother with it since the stock IDE works for me.
Roadmap ExtensionWhile figuring everything out took a while, the extension itself is fairly simple.
When a page loads, the extension checks whether it is being run on either of the two Basecamp sites. If yes — it detects the todo items are shown on the page, sends an API request to the Roadmap server, and displays the necessary information.
To start with, it adds neat “R” icons to each todo that RM knows about. Clicking on these opens a popup with detailed todo information, and it is possible to edit this data, start / stop a timer, or log worked time for the task.
|The red icon stands for “running timer”.
The todo popup shows minimal required data “at a glance”,
allowing to go directly to detailed page in Roadmap itself.
All of this requires quite a lot of user interaction, a number of API requests to the server etc, but the pleasing outcome is that it works.
Browser SupportCrossrider claims support for desktop versions of Chrome, Firefox, Safari and Internet Explorer. In my experience this is true, but there are nuances to be found with each.
Firefox has been the best one to work with. The extension “just runs”, not compatibility issues or any such thing. The browser itself is democratic, not trying to limit how you install your extension or what you do with it.
Yet one significant weakness is that currently it isn't possible to publish Crossrider extensions to Mozilla Addon Directory. which is a huge shame. Extensions fail automatic checks performed on submission, and, having gone through this process myself, I see that the complaints aren't about my code — they are about the code provided as part of Crossrider framework, and thus out of our control. Crossrider team is aware of this, yet it is hard to say whether any progress is being worked on in this regard.
One more problem that I found with Firefox is an incorrect implementation of Content Security Policy (CSP), which could be problematic in some cases. Briefly — same-URL policy, if set by the site, doesn't allow running browser scripts (which includes bookmarklets or extensions) on pages that don't allow loading scripts from other sources. Thankfully, Basecamp doesn't have this, but we saw this while testing with some other task-tracking systems, and I've shared with Crossrider team the result of my investigation in their GetSatisfaction support system.
Chrome, thus, is our main development and distribution platform. The browser itself causes the least pain, everything is compatible, and submission to Chrome Web Store works wonderfully.
|Presentation often means attention.
Google tries hardest to “sell” our extension.
Apple doesn't even bother, and Mozilla doesn't allow us on their store. Sigh.
The only issue that really bothers me is the recent ban on installing extension from sources other than the Web Store. There are “developer” ways to side-step it, so really not an issue, yet I am concerned about the direction that Chrome is heading — from openness to “caring about the users” by limiting them to least possible options.
Which naturally brings us to Safari :) The compatibility of extensions is good when it works, but you'll need to go through several gates of Apple hell before you even get there — running your extension in your browser on your computer requires a special developer certificate, developer tools are quite limited, and there are enough browser quirks to drive a mad person even madder. Best approach I found was to perform all development in Chrome, and then load the result in Safari, testing and debugging the Safari-specific issues.
So while with a bit of sweat and pain, the extension does work on Safari, and we're happily featured in the Safari Extensions Directory.
Did I forget anyone? Ah. Yes…
Don't get me wrong, otherwise I think that IE10 is a huge improvement on the previous versions, but its extension support looks to be an afterthought. May be Microsoft's “Spartan” effort will be better — we'll see.
But for now we decided to support Firefox, Chrome and Safari. This covers an overwhelming majority of our user base.
SummaryYou can tell that I am pleased with this approach. Some development, especially debugging (especially on some browsers) can be fiddly, yet in general it feels great to know that almost any extension (within reason) can be developed using this approach — given time, perseverance and creativity :)
And this is the main takeaway for me — I am glad that this project came about, and that I didn't try to wriggle out of it because “I don't know how to do it” and “This is outside of my expertise”. Turns out, I can do it, and I hope I'll have more new and interesting projects in the future.
We die the day we stop learning.
One thing that I especially wanted to highlight is Crossrider's wonderful support team. They can't always fix everything, some of the more significant issues were communicated to the development team and are still pending, yet they respond quickly, always pay the maximum attention to your request, are willing to check your code and suggest possible improvements, and left me impressed.
No, I am no affiliated with them in any way. I just enjoyed working with their product and communicating with their staff.
Makes me think that doing your job well and treating your customers with care means so much in our hectic world.
Photo: Emmanuel Huybrechts