Call Me Gearhead

By Dimitri Glazkov
Posted on 10/07/07

So, I am playing with Google Gears and I've got to tell ya, Gears are brilliant. And the farther you look, the shinier it gets. Why? Because Gears fulfill the ultimate fantasy of any Web developer in a very radical way: they cut into the browser (IE and Firefox, currently), deep and wide, introducing themselves inconspicuously as a DOM facility (google.gears.factory - hah, clever fellers, aren't they?). And they bring… well, I think they bring a bit more clarity into this whole murky future Web thing. Oh noes, did Dimitri finally cross the line from a grouchy nerd to the full-blown pundit and started predicting the future? Well, let's hope not. To the very least, color me intrigued.

If you're not familiar with Gears, this blog is probably not the place to learn it, but basically, it breaks down to three things: local storage management, isolation/threading model, and cross-origin data and resource access. Yeah, see? It's not even the same breakdown as on their site. But that's why it's here on my blog: I can skim over the details and get to the good stuff. And good stuff it is. I am surprised that the reaction to Gears is so muted, because they attack the status quo of Web application (heck, any Web site) development with a deft balestra that rivals pretty much anything I've seen on the market since, well, since XMLHttpRequest (only took 5 years to «discover» that one, eh?). Here are just a couple of exciting possibilities that come to mind after playing with the 0.2 code.

Client-side Composition

Up until now, whether we are eager to admit it or not, DHTML applications (and I am intentionally classifying SilverFlash out of the picture here) had this distinct flavor of a dumb terminal (Crockford says 3270 — it's catchy. Besides, I still have a 3812 in my basement. Makes excellent ballast). The server had to pretty much “print” down the wire the entire snapshot of a page in a tasty soup of HTML. And that's on every request.

Google pushed the envelope on client-side composition with GMail and some people took notice, but by and large, server-side composition reigns supreme. Come to a page on the Web, and for each ounce of content there is a bucket of context: navigation, branding elements, context-sensitive link lists, spotlights, testimonials, you name it — all repeating from page to page, racking up bandwidth, using up server cycles needed for complex frameworks to sift, sort, transform and align resources into the darned HTML snapshot. And that's on every request, my teary-eyed readers. I would join you in your sorrow for all this wasted energy, but I must finish this song… er, post.

See, with server-side composition, it is up to the server to determine the context of the requested page and generate markup that puts those links and other context elements together with the content of the page. Let's isolate this effort into a separate functional component, and call it the context engine. To summarize, content engine retrieves content of the page, context engine evaluates content and mashes it with whatever seems relevant, and hands it off to be served to the user agent. Funny fact: most modern content management systems are in fact context management systems. Content engine is dumb and simple (fetch a page, duh). Context engine is complex, nontrivial, and a gargantuan resource hog.

With Gears, you can finally have proper client-side storage (not the cookie-based monster), and thus you can have proper client-side state. And thus you can implement proper client-side composition. Which means that aside from the obvious "offlining" of frequently-used, but rarely-changed assets (static pages, scripts, images, stylesheets) using LocalServer, you can actually move the context engine to the client-side… Hey buddy, an example wouldn't hurt, m'kay? M'kay.

Let's suppose that on your site, most pages have a sidebar, displaying the list of upcoming events, relevant to this page. With server-side context page, each page arrives as the blob of markup, generated by the context engine. With client-side context engine, the page only contains:

  • content and optionally, a list of keywords (tags) that describe the meaning of content
  • URL to the event feed

Upon loading of the page, the client-side context engine kicks in:

  1. It checks to see if local event repository exists, and if it doesn't, creates one by fetching all events from the provided event feed URL.
  2. It evaluates content/tags against local content repository of events and adds relevant event to the sidebar
  3. Makes "get added/updated since" requests to the event feed and updates content repository, as well as the sidebar
  4. Removes older events from the repository

When this user goes to the next page, the server doesn't do anything but serve content. For the duration of the session (or perhaps some pre-defined interval), the client-side context engine provides relevant events from its local repository. The happy, unburdened server sends sloppy kisses to Gears. No wonder, because now, the only task that requires any meaningful computation is serving the list of events added or changed since specified date or revision marker. Twitter boys, this one's for you.

Decoupling context engine from the server not only makes server's work easier. It also makes context engine server-independent. Who says that I should only pull events from this one server? Why not pull them from that popular news outlet, online local events site, or Google calendar? Schmancy-Schmashups, here we come!

Even cooler, the client-side context engine is far better suited to keep the track of user browsing habits, generating personal taxonomy or tag cloud, and taking it into the account when evaluating relevancy. Am I the only one who gets goosebumps thinking about the opportunities?

Worker as Service

While playing with Gears' 0.2 bits, I realized that cross-origin HttpRequest and createWorkerFromUrl() introduce a better, more modular and more secure way of building public JavaScript APIs. In this new release of Gears (developer-only, for now), the worker can be loaded from a URL, and this URL does not have to originate on the same server as the document, in which the worker is created. In essence, you can load and run a script from another server in a completely isolated context, and you can exchange messages with this script. And this script can make HttpRequest calls back to that server. It only takes a small logical step to see that this script can expose the public API of a Web application, located on that server, via WorkerPool messaging.

Let's pretend that I have a Web site that wants to use Google Spreadsheet as table, listing some goods for sale. Here's how I would connect to the API using JavaScript (wildly pseudocoding):


	var wp = google.gears.factory.create("beta.workerpool", "1.1");
	// create message
	var getRows = new Message("getRows");
	// ... perhaps create more messages, with parameters or not
	// set up message handler
	wp.onmessage = function(text, id) {
		var message = Message.fromJSONString(text);
		// API initiates communication
		if (message.command == "ready") {
			wp.sendMessage(getRows.toJSONString());
		}
		// ... more message processing
	}
	// finally, kick-start the whole thing by loading the API
	// URL is fictional, of course
	var api = wp.createWorkerFromUrl("http://google.com/api.js");
	

Yeah, I am skipping lots of details, but I hope the concept is obvious: the Spreadsheet API handler is loaded as a worker, and the page can then use this API by exchanging a documented set of messages. No need to knit double-frames or server-side proxies. It just works.

Because the worker is isolated, we can set up more secure authentication and increase authentication granularity by accepting only certain messages, depending on the identity. Also, worker runs as a separate thread, which means we can do other things while the data is cooking. If it were up to me, I'd be staying up all night converting all Google API endpoints to this model and developing a good message exchange protocol. Though I might be getting too old to stay up all night without dire consequences.

Worker as Module

A reverse of worker-as-service model is worker as module. In this case, the application accepts cross-origin worker registration via UI, allowing them to participate via message exchange. For example, Google Reader could allow users to add plug-ins by allowing the users to enter the URL of the API. The URL could be an HTML document with some simple markup, referencing the JavaScript file, containing the plug-in. Easy-peasy. And beautiful.

Thinking Outside of The <object> Box

Finally, let's pause for a second to ponder the way Gears is implemented. Instead of building their own Eden inside of an object node, Gears hook up directly in DOM, without creating a scripting language runtime and certainly not a new declarative presentation format. They organically extend HTML DOM space and DHTML developer's horizon. What's more, the Gearites openly commit to making (and diligently follow through with ) a good effort of helping bring this extension into the new HTML spec. And I like this thinking.

Comments

  1. Re: Call Me Gearhead
    Posted by Anonymous on 10/08/07

    Here's Crock talking about this very thing, at Google no less.

    http://video.google.com/videoplay?docid=452089494323007214

Post your comment

  • Name:
  • E-mail:
  • Title:
  • Comment: