Charlie Cheever

Samasource, a cool non-profit in San Francisco is looking for an engineer. They help poor people all over the world get out of poverty by giving them jobs and helping them learn skills.

From my friend Leila:

Web Development Maestro

Samasource’s engineering team builds innovative systems that support the organization’s rapid growth. We need a scary-smart engineer to expand this effort. If you join us, you’ll play a key role in architecting and building an interactive platform that will be used by people all over the world to better their lives.

Specifically, we are looking for:

* 2+ years of web development experience
* Expert-level (dare we say even Maestro-level?) facility in Ruby on Rails or PHP
* Knowledge of website usability and web development
* Ability to learn quickly and adapt to change

If you are interested in joining our engineering team or have any questions, please send an email to info@samasource.org with a summary of your interest and availability, as well as a recent CV. Please include “Web Development Maestro” in the subject line.

Alma Networks is a startup founded by Adam D’Angelo, who was previously CTO and VP of engineering at Facebook, and Charlie Cheever, who led Facebook Platform and Facebook Connect. We’re working on building a community-generated database of the trusted information that interests people most. Some of the challenges are highly algorithmic, such as coming up with ways to organize and categorize the information effectively so that users can efficiently find what they need; others are very technical, such as working to make a web application that is complex while still being very fast; and many of the challenges are in product design, such as figuring out a way to set up and grow a healthy community and constructing intuitive interfaces for users. Alma Networks is based in Palo Alto, CA and has seed funding.

We are committed to building a cutting-edge technology company that develops software the right way and is a place where engineers love to work. Some of the tools we are using include Python, Pylons, memcached, Thrift, and git. We’re using continuous deployment and EC2, so all code you write will go live to production within minutes no matter what time it is. Both founders are developers. We want to build a fantastically strong engineering team and the first engineer that joins us should set the tone for that.

Requirements:

B.S., M.S., or Ph.D. in Computer Science or equivalent.

Extraordinary software engineering talent.

Substantial experience developing web applications.

Knowledge of TCP/IP and network programming.

Experience with compilers, distributed systems, and machine learning a plus.

The number of years of professional experience you have isn’t important to us.

You should be ready to make this startup the primary focus of your life.

In the short run, the most important thing is to release our first product, and so it is critical that you can be immediately make big contributions to our complex web-based application. In addition to working with us in writing the software, the ideal candidate should be proficient outside the technical realm–making good product decisions, designing user interfaces that are both pretty and functional, being an effective marketer and recruiter, and being capable of handling anything else that comes up. You should also be fearless and broad inside the technical realm, happy to tackle CSS and JavaScript as readily as you are to take on optimizing the performance of a backend service in C or Java. You should be ready to jump down into C and write an interpreter for a simple language if necessary, or hook up a cluster of machines to run a distributed machine learning job you wrote. In general, you should be very good at getting things done outside your comfort zone.

You will be required to make good decisions about important things without much oversight. You should be comfortable with autonomy and ownership of large areas of product and infrastructure. It’s a plus if you have worked on projects in your spare time, such as programming games in middle school or high school. An ideal candidate will have the potential to grow into a strong leadership role over time–in either a technical or management capacity (i.e. eventually the equivalent of a Google Fellow or a V.P.)

We think we are working on something that is very important and that lots of people will use every day. If you’re interested, e-mail us at jobs@alma-networks.com.

For someone who is talented but not super experienced, this should be a great opportunity to learn a whole lot very quickly. And for someone who is more experienced, I can say it’s a super fun project to work on that I’m really excited about.

My favorite font for doing programming and other fixed-width things has been 9×15 from X11 for a long time. It’s readable and clean and a good size. I’ve been using HyperFont and Monaco since I got a Mac a few years ago, but they just aren’t quite as good.

So, today I spent some time converting a BDF version of 9×15 to a dfont version using FontForge.

It looks like this:

I’m sure that someone else has done the work to make a Mac version of this font before, but since I couldn’t find anything while searching, I’m posting my conversion on this blog.

Recently, Facebook opensourced a tool I wrote in 2007 called bunny1 which lets you write smart bookmarks in python and share them across all the browsers you use and with a group of people (like a company). It has always been pretty hard to explain what bunny1 does but most people who have started using it find it really useful once they’ve started; personally, I now find it painful to use a browser without it. I’ll work through some examples of how bunny1 gets used at Facebook in this post to try to convince you that bunny1 is worth checking out.

A Command Line for Your Location Bar

The basic way that bunny1 works is like a command line for your location bar in your browser. Instead of typing URLs, you can type shorter things that are easier to remember. So, for example, you could type expensereports into the location bar instead of typing in http://www.thirdpartyexpensereportingprovider.com/yourcompany/login.aspx.

Browsers currently solve this problem by having a bookmarks toolbar or favorites menu, and Firefox lets you give “keywords” to your bookmarks which you can enter into the location bar instead of clicking. Firefox lets you parameterize your bookmarks to make something called quicksearches. If you bookmark the URL, http://www.somesite.com/?q=%s and give it the keyword somesite, then if you type somesite somesearch into your location bar, Firefox will go to the URL http://www.somesite.com/?q=somesearch . In 2005, Jon Aquino made a pretty interesting service called YubNub that let people share quicksearches. It works really well for common searches like Google search, Yahoo! search, Wikipedia search, Flickr image search, etc.

bunny1 is similar to YubNub, except that instead of having one global namespace of bookmarks that everyone shares, you can run your own server which means that you can put in bookmarks that are private to you (behind VPN) or give really short names to bookmarks that are really important to you but aren’t important to other people (ex. at Facebook, bz points to the Bugzilla instance for Facebook Platform). The other interesting feature of bunny1 is that all the logic for the commands is done on the server side, which means you can write your bookmarks with just a few lines of python and they are version controlled, and it means that its easier to add complicated logic to the way that inputs are handled. Since YubNub’s database of common quicksearch commands is pretty good for many basic things, the default behavior of bunny1 is to fallback to using YubNub if it doens’t understand what the user has entered. This means that many common commands like searching the PHP documentation (php on YubNub) come for free.

My guess is that the biggest reason that YubNub hasn’t really caught on is because Google Search has pretty much solved the navigation problem for the open web. If I want to schedule an appointment with the California DMV, I just type something like california dmv appointment into Google and I usually end up at the right place. And if I want to look up Jason Priestley on Wikipedia, a Google search for wikipedia Jason Priestley or even just Jason Priestley is a pretty good way to get there. But searching Google for facebook internal wiki coding standards both doesn’t work (since Google can’t index Facebook’s corporate intranet) and is also a lot to type. So I think its generally useful to have a domain-specific YubNub.

Smarter Quicksearches

If you use quicksearches in Firefox, you’re used to being able to make parameterized bookmarks. Many people have g some search termas a shortcut to searching Google. With bunny1, you can do the same thing, but since the commands are written in python, its easy to put more sensible logic in place where it makes sense. For example, at Facebook, there is a command appabout which can be parameterized with either an id number, API key, or the short canvas name of an app. It’s easy to set this up with just a few lines of code:

A simpler example would be that the fb command either searches Facebook for a search term, or if none is given, just goes to the Facebook homepage.

It’s also pretty easy to write in more complicated syntactical elements into your commands. A few examples that are really useful at Facebook are:

SVN revisions.

If you just put something like r146630 into your location bar, it will take you to that revision in our Trac instance. This is really convenient when copy/pasting things from e-mails, etc.

Switching between staging environments

When doing development at Facebook, its pretty common to want to view a specific page on the live site, using the current tip of the trunk of the codebase, or in a particular sandbox. Switching between these requires changing some parts in the middle of the subdomain, which is often painful to do manually. Using bunny1, you can just put something like @live, @dev, @sb, @ccheever.someserver, or @beta before the URL in the location bar to jump between these different environments very quickly. This speeds up investigation and debugging of some common problems.

Referring to people.

One thing that’s pretty common at Facebook is wanting to go to a particular person’s profile. It’s not too terrible to do this on facebook.com since we have typeahead search, but it’s really nice to be able to type p vernal into the location bar and go right to Vernal’s profile. In the Facebook instance of bunny1, there is a decorator that makes it really easy to mark commands as ones that should be parameterized by people, so you can also do wall (corson) (j wang) to see the wall-to-wall between Dan and Jwang. The code for a command like this just looks something like this:

and the name to user id substitution happens automatically. Since the commands are all written in python code, its easy to make abstractions that make writing similar useful commands really easy.

It’s also pretty useful to have shortcuts for searching different services in a corporate setting. At Facebook, some of the most popular are iw for searching the Facebook Internal Wiki, c for searching the internal bugs database, mla for searching the archives of mailing lists, fb for searching the website, bz for searching the Facebook Platform Public Bugzilla Database, and devwiki for searching the Facebook Developer Wiki, and a few others as well. Making it take less time to execute these searches actually makes a meaningful difference in productivity for people who do any of these operations many times each day.

There are also a fair number of commands that aren’t just bookmarks or searches but have side effects. An example of this would be the merge command which lets you request the merge of a particular commit into the release branch.

Ubiquity

bunny1 is similar in many ways to a fantastic Firefox add-on from Mozilla Labs called Ubiquity. Ubiquity is pretty much bunny1 on steroids and absolutely something you should install if you use Firefox. The main difference is that Ubiquity is a Firefox add-on so it can do very powerful things like access your e-mail contacts, but it only works on Firefox. In the fullness of time, I expect that a version of Ubiquity will be released for pretty much every browser and the product will continue to mature, and everyone will use Ubiquity for everything. But for right now, there are a couple reasons that I still use bunny1.

Portability

bunny1 works pretty well across all browsers while Ubiquity only works in Firefox. Almost every day, I use Firefox, Safari, IE, Chrome, sometimes Opera, and occasionally more exotic browsers like WebKit nightly builds. It’s really nice that I can use bunny1 with all of them.

Also, since bunny1 is a server, my bookmarks are always in sync across the different computers that I use. There are ways to set up syncing of things like Firefox configuration across different machines and Ubiquity subscriptions also help with this problem, but getting these things right takes a lot more effort than just hooking up to the same bunny1 server.

Speed

Since the UI for bunny1 is typically the location bar, my cursor is there already when I open a new tab. And since bunny1 is scoped, its normal to make any command that you use frequently have a really short name even if you don’t think everyone in the world would use that command a lot, (ex. iw for searching Facebook’s internal wiki).

Its also slightly less work to add commands to bunny1. One point of comparison is that Jono DiCarlo has a good screencast showing how to write Ubiquity commands where he works through the example of writing a command to find your congressional representatives by zip code in about 10 minutes; I added an equivalent command to the bunny1.org instance of bunny1 in just about one minute. (It probably would have taken 2-3 minutes if I had been explaining and screencasting and it would definitely be possible to streamline the process described in the screencast, but there is just less stuff you have to do to make a command in bunny1). These days at least, most of what people want to do with tools like these is go to a specific URL (ex. the YouTube subscription center) or go to a specific URL with a given parameter (ex. search Google for some phrase), so having it be as easy and fast as possible to add these kinds of commands is a really desirable property.

When I run Firefox, I actually use Ubiquity and bunny1 at the same time, and use bunny1 for navigating and searching common sites, and use Ubiquity for fancy things like embedding a Google map in my e-mail or translating in-page or e-mailing my grandmother my entire image browsing history.

The Facebook bunny1 Setup

At Facebook, there is an instance of bunny1 called lolbunny that runs on a few machines that are publicly accessible (for redundancy; the resources it requires are negligible. The first time that a person accesses the instance, he or she must be inside Facebook’s VPN. If this is the case, a special cookie is set on the browser which lets the user access lolbunny.

We made lolbunny publicly accessible so people could use it even when they weren’t on the VPN. It does mean that someone could steal the cookie and get access to lolbunny, but since lolbunny mostly just serves up redirects, that would just give you some vague ideas about the URL structure of the Facebook intranet but not access to any really sensitive information.

I’ve been planning to run my own bunny1 server on one of the domains I own, and then have that fallback to Facebook’s server for commands it doesn’t understand, but since I don’t do much navigation to things that aren’t either work or common enough to be handled by YubNub, I haven’t gotten around to doing this yet. At times, I’ve run a instance of bunny1 locally on my Mac, but it’s annoying to make sure the server is running between restarts, and it doesn’t achieve the portability that running one instance in the cloud for every browser does.

If you create a Facebook application, one of the most confusing parts of setting it up is choosing whether to make your app use IFrames or FBML as the default for your application’s canvas pages.

The text explaining the choice is:

Your application will be viewable in the Facebook navigation at this URL – either as rendered FBML or loaded in an iframe. If you aren’t sure what you should use here, choose FBML. You can use iframes within FBML on canvas pages with the <fb:iframe> tag, and most things you will want to do will be easier and faster with FBML.

But over the last few months, there have been a few developments which have made that explanation of the choice out of date. I think it is now easier to create a better app by using IFrame canvas pages than it is with FBML. I’ll try to explain the difference between the two paradigms, some of the things that made FBML a better choice originally, outline what’s changed since then, and make some conclusions about what techniques you can use to make the best performing applications. Ray wrote a post on the official Facebook Developers’ Blog about enhancing IFrame-base applications a few weeks ago, which overlaps a lot with this post, but I think its worthwhile to go into a little more detail around the choice between FBML and IFrames.

How a traditional IFrame canvas page worked

IFrame canvas pages are pretty straightforward. When the user loads a page on Facebook like http://apps.facebook.com/yourapp/somepage, Facebook serves up a webpage that has the Facebook chrome around a big IFrame. The IFrame that gets opened is something like http://www.yourdomain.com/callbackurl/somepage?fb_sig_in_iframe=1&fb_sig_locale=en_US&fb_sig_time=1221720862.9318&fb_sig_api_key=48102584111d14a9c2e41dd28ea637d7&fb_sig=e656792696ae913c1fc34eeff2d79f75

The fb_sig parameters give more information about which user is logged into your application, let you verify that the request is indeed coming through Facebook, etc. You can put whatever you want into the Iframe and it will be rendered there.

Usually in a Facebook app, you’ll want to include some social content like names and profile pictures, and sometimes you’ll want to get some data from the Facebook API to determine which content to show. The way you can show this content without using FBML is to get the information you need via the API and render it yourself.

Here’s a rough diagram of how all this works:

Traditional Iframe Canvas Page

How an FBML canvas page works

FBML canvas pages are a little bit different but are still pretty straightforward way. When the user requests a page like http://apps.facebook.com/yourapp/canvaspage, Facebook doesn’t send back a response right away; instead, the Facebook server will send a request to your app’s server. This will be an HTTP POST to some URL like http://www.yourserver.com/callbackurl/canvaspage. The fb_sig parameters will be sent as part of the POST rather than as part of the URL. Facebook will expect some FBML back and then turn that FBML into HTML and send it back to the user’s browser. FBML is mostly the same as HTML, but using FBML lets you include social content inline in your markup.

So, if you want to show things like names and pictures in FBML, you don’t need to make calls to the Facebook API; you can just use tags like <fb:name> and <fb:profile-pic> to reference the data directly. If you want to use data like birthdays, etc., then you’ll still need to use the API the same way you would on an Iframe page.

Here’s a diagram of how an FBML canvas page works. A lot of the time, you won’t need to make any API calls, so those arrows are dotted in the diagram.

FBML Canvas Page

Why We’ve Been Recommending FBML Up Until Now and What’s Changed

There are a bunch of nice things that FBML provides for you which is why we’ve been recommending that developers use it. But over the past few months, we’ve been doing a lot of work–mostly as part of Facebook Connect–building stuff that you can use to get most of those advantages and more for your IFrame canvas pages. The ones that I think are most important are:

Speed

FBML pages have tended to be faster for a bunch of reasons. For one thing, many FBML canvas pages don’t end up needing to make any API calls, and when that happens there is one fewer roundtrip that needs to be made if you are using FBML. Another thing that has tended to make FBML canvas pages perform better is that Facebook’s servers are directly peered with most of the large hosting companies that serve app pages, so the latency on the roundtrip from Facebook’s servers to your application can be much smaller than the latency from the user’s browser to your application’s server. There is also some non-trivial overhead from setting up an Iframe on most browsers but I believe this is fairly small compared to the other two things listed here.

What’s Changed: Facebook Chat and XFBML

Facebook’s released two things in the last year that really change this up: Facebook Chat and XFBML. The reason that the launch of Facebook Chat is important is that its now really expensive to setup a page with the Facebook chrome since the chat bar involves a lot of JavaScript and CSS which have to get executed and rendered by the browser from scratch on each page load even if the files are cached on the browser. On the first page that a user loads from your app, both FBML and Iframe apps will have to pay this cost; but on subsequent page loads, an FBML app will incur this cost each time but an Iframe app will just involve switching the page that is inside the IFrame. IFrames always benefitted from this, but now that setting up a Facebook page is a bigger chore, this is a bigger deal.

While Facebook Chat makes FBML canvas pages slower, XFBML can make IFrame canvas pages faster. The big disadvantage for IFrame canvas pages in terms of speed was having to make an API call to Facebook before sending back content to the user’s browser. XFBML lets you avoid that. With XFBML, you can embed some simple FBML tags like <fb:name> and <fb:profile-pic> directly into the HTML that your app sends to the user’s browser, and when you include some JavaScript from Facebook, code will execute that scans the DOM for those tags and then figures out all the data needed to render that content and batch that up into one API call from the user’s browser to Facebook. The rest of the page that isn’t social content can render to the user before this happens, and in XFBML, we cache data on the browser so that in many cases, it isn’t even necessary to make any API call to Facebook at all. This all adds up to making IFrames a snappier experience in most cases — though sometimes you might still need to make server side API calls to Facebook if you want to do something like show a page with upcoming birthdays.

We developed XFBML as part of Facebook Connect as a way to quickly get social content onto any webpage, and since IFrames are just webpages, XFBML can speed those up as well.

Here’s a diagram of how an IFrame canvas page works using XFBML on the first page a user loads from your app:

IFrame Canvas Page Using XFBML - First Page Load by a User

At a glance, this looks worse than the scenario for Iframe canvas pages that don’t use XFBML, but if you use XFBML, then you usually won’t need to make an API call to Facebook from your server (which means (4) and (5) don’t happen), and the user’s browser will be able to start rendering most of the page–everything except the XFBML content its waiting to get from Facebook–right after (6).

On subsequent page loads, the benefits are even greater. Here is a diagram of what that looks like:

Iframe Canvas Page Using XFBML - Subsequent Page Loads by a User

Note that in this case, the original request to Facebook and response to the browser don’t need to happen anymore, and the JS API calls will sometimes be unnecessary here as well if the necessary data has been cached on the client. In this scenario, your app should be basically just as fast as a regular website except that the social content will fill in just after the page has rendered which can result a little flicker on some browsers.

Convenience

We’ve heard from developers that FBML has been simpler than using the API in two ways.

FBML is really nice when its important to batch your data access

It is actually a pretty gnarly problem to figure out all the data you are going to want on a page up front, and as your pages get more complicated, this problem gets more complicated too. One solution is to produce code that has two sections: the first which figures out all the data you need and fetches it from the API and then stores the data in some variables in your program, and the second part which renders all the HTML that you want using the data stored in those variables. This technique can work, but it is a little bit tedious and hard to maintain if you want to change anything since you have to make changes in two places. You’re also likely to make mistakes in this scenario where you remove something from the rendering section but forget to remove the corresponding data access entry and then are requesting data you don’t need which is hard to notice and inefficient. Things get even worse if you try to build modules that can be reused across different pages. An example of this would be a module that displays which of your friends are online and prompts you to interact with them. In that scenario, you either end up writing two sections of code for each of your modules, which is the same pain as described above but multiplied by the number of modules you have.

The other solution you could use besides a two-pass approach would be to create a system of placeholders that describe the data they need. If you do this, you can have one piece of code that doesn’t change that scans all the placeholders and makes a big request for all the necessary data and then fills it in right before you send your rendered response back. This is essentially what FBML is, and so FBML is convenient in that we do this for you and optimize it as much as we can so you don’t have to build this system or work on it.

FBML is nice for Facebook-provided widgets and dialogs

There are ways to render things like the multi-friend selector widget and feed forms when using Iframes, but these are often a bit clunky compared to doing these in FBML. There are also some useful widgets that are provided as part of FBML like fb:share-button that are a pain to recreate on your own (though certainly possible). I’ve heard from developers that fb:dialog is a really nice way to make a popup dialog with a few options. If you want to make an application that is consistent with Facebook’s look and feel, these tags can make that task much easier (though some of them can cause headaches because they aren’t tweakable enough).

What’s Changed: XFBML gives you access to all this within Iframes

In addition to being able to embed things like fb:name and fb:profile directly into your HTML which makes doing efficient data access easier, you can use any FBML tag in XFBML by using server-side FBML. If you wrap your FBML inside the tags <fb:serverfbml><script type="text/fbml"> ... </script></fb:serverfbml> then an Iframe will be opened to Facebook on the page being served from your domain, and we’ll render the FBML in there.

There’s a fair amount of overhead involved in opening the IFrame and your CSS won’t propagate into the FBML IFrame, so you won’t want to put too many blocks of server-side FBML on a page, but if you just need one or two snippets of FBML to make your life easier, or you want a large chunk of your page to use FBML, this makes that possbile and pretty easy.

Looks

One thing that often makes IFrames look ugly is that they have to be declared to have some fixed size and then if any content exceeds that size, nasty scroll bars appear (or the overflowing content is inaccessible to the user). Early IFrame apps on Facebook often looked very ugly for this reason despite a cursory “smartsizing” solution that we implemented. Most developers ended up creating giant IFrames with heights larger than they ever expected their content to get which was a little better but obscured the page footer and made the scrollbar unintuitive.

What’s Changed: Now, there’s an easy way to get your IFrame to resize automatically

Preload FQL and the List of Friends for Free

It’spretty common to know what FQL queries you need to make to generate a page even before the request comes in from a user. For example, if you want to make a page that shows a calendar of friends’ birthdays, then you know you’ll need to make an FQL query that returns all the birthdays of all the friends of the user. We added a feature about a year ago called Preload FQL that has let you do this on FBML canvas pages. You just have to specify a few regular expressions that map to lists of FQL queries, and if the page being requested matches any of the regular expressions, the corresponding FQL queries will be executed by Facebook when the user’s browser sends the request to Facebook and the results will be sent along to your app’s servers when Facebook requests the FBML from you. Most of the time, this makes calls to Facebook’s API unnecessary, even when you need fairly complicated data from Facebook to generate the page.

This is what the flow would look like for an FBML canvas page using preload FQL:

FBML Canvas Page Using Preload FQL

In the diagram above, the FQL query is executed after (1) and the results are sent along to your application server with (2).

What’s Changed: Now, there is a way to do something similar in IFrames

With IFrames, there isn’t an easy way for Facebook to send data to your server along with the request for the IFrame except by encoding data in the URL being requested, so In both cases, instead of sending the FQL result set to your server, the Facebook server sends the FQL result data down to the user’s browser–attached to the outer frame that contains the Facebook chrome on the canvas. You can choose whether you want to have a lightweight redirect happen which will encode the FQL results in the request made for your IFrame page, or if you only want to access that data on the client side, you can skip that and just use the PreloadFQL_get method from the JavaScript client library and rewrite parts of the page on the fly using the data after its initially rendered.

Here’s a diagram of how this works:

IFrame Canvas Page using Preload FQL

Note that the preload FQL will only work on the first page that loads in your IFrame. (If you point your links to apps.facebook.com URLs using target="_top" instead of just linking to different pages within the frame, you could use preload FQL on every page, but this would make all your pages load slowly. We may make some mechanism for directing the containing frame to make API calls which could then be fetched across pageloads within the IFrame if there is a lot of demand for that. In the meantime, if this is important to you, it should be possible to roll your own mechanism for this by wrapping your IFrame canvas pages within your own extra IFrame.)

This paradigm is a bit different from the way the Preload FQL works with FBML canvas pages, and if you’re a traditional web developer, having to send down JavaScript that will access the data and then rewrite the page is awkward. But developers who have written substantial OpenSocial applications or AJAX-intensive web apps should be pretty comfortable with the way this works.

We also send the list of the user’s friends to the containing frame right away so calling the friends_get method from the JS API client also won’t require a roundtrip to the server now.

URLs

One thing that’s annoying about IFrame canvas pages is that when a user navigates through your app, the location in the URL bar never changes; it always stays on whatever the user went to (unless you specify target="_top" on your links, but that means that you’re incurring all the costs of a first page load again which is much slower.)

Unfortunately, we don’t have a solution for this right now. For many applications this isn’t a big deal at all, but its inconvenient for users who want to make bookmarks or copy links to send around, etc. We’re planning to add a mechanism similar to automatic resizing where some JavaScript from Facebook that executes in your IFrame communicates its location to the embedding Facebook page which can then manipulate the fragment of the URL (the part of the URL after the #) without causing the browser to reload the page, but we haven’t gotten around to doing this yet. (I’ll try to remember to update this post when we do.)

Authentication

On FBML canvas pages, the request for FBML that is sent to your application server contains POST data that lets you learn and verify that the request is coming from Facebook on behalf of a particular user. If that user has a session with your application, then the session data you need to make API calls on behalf of the user will be passed along as fb_sig_session_key in the POST. Most client libraries handle this pretty seamlessly, and so you don’t have to think about it.

On IFrame canvas pages, things don’t work as well. Facebook passes fb_sig_session_key to your IFrame as a GET parameter in the querystring of the IFrame’s URL. As with FBML canvas pages, most client libraries make this pretty painless and invisible to the app developer; but there are two pretty big flaws with this approach.

Browsers can leak the session key via the HTTP_REFERER field. This is a pretty serious security flaw in our design, and it is pretty easily exploitable if you let users post public links or images. One way you can fix the problem with links is by sending all links through a redirect, but that doesn’t solve the problem for images. It is currently not safe in an IFrame canvas page to reference images that users have given you the URLs for without proxying or caching those images yourself.

The other problem with passing the session information around as part of the URL of your page is that it makes it inconvenient to link to pages within your app without losing the session information. One way to handle this is to make your links point to canvas pages (like http://apps.facebook.com/youriframeapp/nextpage.py) and set target="_top" on the link. This technique means that you don’t lose session information but means that your application incurs all of the overhead of setting up an initial IFrame canvas page which leads to a pretty clunky feeling application experience. Another technique you can use is to link to other pages that are off your canvas URL (ex. http://yourdomain.com/appcallback/nextpage.py) and manually append all of the fb_sig parameters to the querystring. The major problems with this approach are that if a user opens that page in a new tab or copies and pastes any of those links, then the Facebook chrome gets lost, and all sorts of problems can happen with the session information (the session may have expired, the session might be for a different user than the person viewing the URL, etc.), so this isn’t a desirable choice either.

How to Deal with This Problem

Unfortunately, Facebook doesn’t provide any great out-of-the-box solution here, but a solution that I think might work well could be something like this: the session information gets sent to the containing frame and is stored in the DOM. The URL for the IFrame doesn’t have any fb_sig session information encoded in the querystring. Instead, that information gets stored in a cookie on your app’s domain so that the user’s browser passes it to your server with every request. If there’s no authentication information in the cookies when your server gets a request, then your server can send back a page that is just some JavaScript that communicates with the containing frame to find out the session information and then sets the cookie and then reloads itself. In this solution, it each IFrame page that your server sends to the browser should also probably contain some JavaScript that would verify that the session information in the cookies matched the session information in the containing frame, and if it didn’t, then the cookie would be set to the right information and the page reloaded. It is probably also useful to pass to the first IFrame page that is loaded some fb_sig parameters that your server can use to verify that the session in the cookies is still valid and for the correct user to prevent exploits where a malicious user could load a canvas page with stale cookies and capture the contents sent to the browse for another user before the JavaScript reset the cookies and forced the reload. If you see any major flaws with this solution or can think of a better one, please share that in the comments on this post or e-mail me.

Update: Ted Suzman reminds me that setting cookies doesn’t work in some browsers (Safari) for IFrames of domains other than the one in the location bar, so this solution won’t work for all browsers. I’m sure there’s some other good solution to this though.

I think we’re fairly likely to get around to implementing something to make this easy in the next month or two, but until then, it might be worth rolling your own workaround for these issues.

What All This Means

Now that we’ve made all these improvements that can make IFrame canvas pages better, here is how I would list out the advantages of the two methods:

FBML

Is likely to be faster on first page loads

Fewer moving parts are involved and the paradigm is closer to that of the traditional web

Gives you easy access to lots of Facebook elements

Lets pages in your app have nice URLs

Has a sensible authorization mechanism

IFrames

Is likely to lead to a faster experience for users over the long run

Lets you use the JavaScript, HTML, and CSS that you are used to

Even though there are more bullet points listed as FBML advantages, I think using IFrames for canvas pages is probably a better choice since the two advantages of IFrames are pretty important. In particular, if you are doing a lot of AJAX in your application, it will be snappier in IFrames since the requests don’t need to go through Facebook proxy. And while FBML and FBJS are trivial to learn and shouldn’t scare anyone at all, it is probably easier to debug regular HTML and JavaScript than FBML and FBJS given the tools available today. And if you want to use a popular JavaScript library like jQuery in your application, you can do that the regular way in an IFrame, but you’d have to make some modifications to the library to use it in FBJS, and some things just wouldn’t work.

That said, there are a number of things we’re likely to release in the future that will bring FBML and IFrames even closer to converging on a point of parity. I’m not sure of a timeline for any of these things, and this list certainly isn’t exhaustive, but some obvious improvements that we should execute on are:

Making a mechanism for an application IFrame to communicate page transitions to the outer frame so that the URL changes in a linkable way when a user navigates around an IFrame application.

For IFrame apps, building a way for API calls to be executed in the outer frame so that results can be requested prior to page transitions of the IFrame. It might also be useful to provide a general cross-page client-side caching mechanism by attaching cached data to the containing frame.

For FBML apps, make it so that the content inside the chrome can change without a full browser page load. We do this for many pages on our site (you might notice funny URLs like http://www.facebook.com/profile.php?id=1160#/profile.php?id=219770 that are a side-effect of this), and between avoiding the generation and render time of the chrome and avoiding the processing of all the JavaScript and CSS, it turns out to be a big win.

Create a new version of FBJS that is much closer to regular JavaScript (so you can include your favorite JS libraries without modification)

Once those things are done, FBML and IFrame canvas pages should be similar in performance and ease of use. And now that fb:serverfbml has been added to complement fb:iframe, what you choose to use for your app isn’t that important since you can switch between the modes fairly easily. For most applications, I don’t think IFrames are so much better right now that it would make sense to convert an existing FBML-based application to one using IFrames instead, but if you’re unhappy with the speed of your app, it may be worth a try.

In brief, if you use the new features we recently released, using IFrames for canvas pages is probably a little bit better choice than using FBML for canvas pages.

I’ve heard from a few developers who’ve switched over to IFrames and used the new stuff that they’ve seen good results doing this, but I haven’t had time to do any benchmarking myself. If you try switching from FBML to Iframes and measure your performance before and after, please leave a comment about how much faster (or slower) the load time became. If IFrame performance is significantly better for most apps then it might be worth doing the conversion from FBML to IFrames for some developers.

Two Last Tips

If you’re using FBML for your canvas pages and you decide you want one of your pages to just be an IFrame, don’t use fb:iframe for that. Instead, you should use the fb_force_mode querystring parameter to switch modes which will accomplish the same thing without incurring a roundtrip to your server just to fetch the fb:iframe tag. Similarly, if you are using IFrames for your app but want some particular page to be an FBML page, you can use fb_force_mode to force a switch to FBML. If you find documentation that advises using fb:iframe for switching from FBML to IFrame mode, it was probably written before fb_force_mode was released; we should have all those instances cleaned up soon.

If you’re using IFrames for your canvas pages, don’t set all the links to have target="_top". That will cause a full reload of the Facebook chrome plus an extra to request to do that and generate a new IFrame which will be pretty slow. If you are using an IFrame within an IFrame (or even deeper nesting) and so you need to set a link target explicitly, the IFrame that is your canvas is named iframe_canvas so you should just be able to use that as a target.

Posted on September 11th, 2008 by ccheever. Filed under Uncategorized.

There’s been this trend over the last few years where web browsers are assuming more and more of the properties of operating systems. Google Chrome in particular looks to have been a conscious effort to take a step forward on this front. It has one process per tab now, a pretty close analog of when operating systems started doing true multitasking in the late ’80s, etc. And the addition of Gears is part of a trend that’s been happening where people have been using different technologies to have their websites dig deep into desktop functionality (persistent storage, access to devices, etc.

One annoying thing about the web browser as an operating system is that its not very easy to switch between different applications. If I hit Alt-Tab (on Windows), I usually see 20 different Firefox icons, and I have to slowly flip through them and read the titles to figure out which one is the browser window I want to switch to. On a Mac, its even worse, since I only see one Firefox icon, so I have to switch to Firefox and then hit Command-Tilde a few times to flip through windows until I find the one I want.

A really simple way to make this a lot better would be to just have the browser’s icon switch to be the favicon of whatever website was in the current tab of that window. This would let me do stuff like keep Lala or a spreadsheet open in a window that I could switch to as easily as I can switch to iTunes. I’d love to see some browsers take this approach (maybe it would make sense to have a miniature version of the browser’s logo in the corner of the icon so you had some idea as a user that you were switching to your web browser).

The other thing that happens with operating systems is that over time, stuff that everyone finds useful tends to get built into the operating system since its convenient to have everyone using some standard. Examples of this are ways of playing sound and window managers (the ability to play MP3s and the Finder are both built in to OS X but had analogs that needed to be custom installed on early computers, for example). There are a bunch of things that would be really useful to have built-in to the browser that aren’t right now. One example would be that browsers could keep track of the identity of a person instead of having every website do it individually in its own special way. This would have some downsides but a good browser implementation would let you manage multiple identities while a single browser was open, just like you can do with su on Unix. This kind of mechanism would likely help address the massive phishing problems that are sweeping every important password-protected service on the web right now since users could learn to only enter credentials into security dialogs provided by the browser (which is easier to learn than deciphering URLs). Another example would be that it would be nice for browsers to send geo-location information to services that they contact (1). This would be better than the current system where services use some IP-to-location mapping which is often inaccurate, and is often creepy (e.g. when a user goes to a new website he/she has never visited and sees ads for singles in his/her zip code.) The last time this kind of thing happened in a browser was when IE started accepting favicons. The protocol they choose is kind of lame — sending a second request all the time for a file in Windows icon format only, but I think its still overall good that some way for this to happen exists (the idea I suggested above of using the favicon of a website as the icon of the browser would be much more farfetched without favicons existing already.) (2)

Since the browser market is so fragmented and the web is so standards-driven right now, I think its unlikely that much progress will be made quickly in building these things into browsers or HTTP, etc. I think Flash is probably in the best position to push a lot of this stuff forward since it is ubiquitous but controlled by a fairly small team and so they can make big changes more quickly.